v1
This commit is contained in:
parent
b30baca81a
commit
2a74e9787f
122
assets/css/custom.css
Normal file
122
assets/css/custom.css
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
|
||||||
|
body {
|
||||||
|
background-color: #121212;
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'%3E%3Cg fill='%231a1a1a' fill-opacity='0.4'%3E%3Crect x='0' y='0' width='100' height='1'/%3E%3Crect x='0' y='0' width='1' height='100'/%3E%3C/g%3E%3C/svg%3E");
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-neon {
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
-webkit-backdrop-filter: blur(10px);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
border-radius: 16px;
|
||||||
|
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
|
||||||
|
transition: background 0.3s ease, box-shadow 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-neon:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Typography */
|
||||||
|
h1, h2, h3, h4, h5 {
|
||||||
|
font-family: 'Poppins', sans-serif;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 2.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animations */
|
||||||
|
.card-neon {
|
||||||
|
animation: fadeIn 0.5s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover,
|
||||||
|
.btn-secondary:hover,
|
||||||
|
.list-group-item-action:hover {
|
||||||
|
transform: translateY(-3px);
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero {
|
||||||
|
background: linear-gradient(rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.7)), url('https://images.pexels.com/photos/159888/pexels-photo-159888.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1');
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
|
color: white;
|
||||||
|
padding: 100px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero h1 {
|
||||||
|
font-family: 'Poppins', sans-serif;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 3.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero p {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background: linear-gradient(45deg, #FF4B2B, #FF416C);
|
||||||
|
border: none;
|
||||||
|
padding: 15px 30px;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover {
|
||||||
|
transform: translateY(-3px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
background-color: transparent;
|
||||||
|
border: 2px solid white;
|
||||||
|
padding: 15px 30px;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: white;
|
||||||
|
transition: background-color 0.3s ease, color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary:hover {
|
||||||
|
background-color: white;
|
||||||
|
color: #121212;
|
||||||
|
}
|
||||||
|
|
||||||
|
.features {
|
||||||
|
padding: 80px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-icon {
|
||||||
|
font-size: 3rem;
|
||||||
|
color: #FF4B2B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
background-color: #1E1E1E;
|
||||||
|
padding: 40px 0;
|
||||||
|
color: #A0A0A0;
|
||||||
|
}
|
||||||
77
communities.php
Normal file
77
communities.php
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->query('SELECT * FROM communities ORDER BY name');
|
||||||
|
$communities = $stmt->fetchAll();
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Communities - Community Hub</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
</head>
|
||||||
|
<body class="d-flex flex-column min-vh-100">
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="navbar-brand" href="index.php">Community Hub</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<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="index.php">Home</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link active" aria-current="page" href="communities.php">Communities</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="profile.php">Profile</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="messages.php">Messages</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
|
<main class="flex-grow-1">
|
||||||
|
<section class="container mt-5">
|
||||||
|
<h1 class="text-center mb-4">Welcome to the Communities Page</h1>
|
||||||
|
<div class="row">
|
||||||
|
<?php foreach ($communities as $community): ?>
|
||||||
|
<div class="col-md-4 mb-4">
|
||||||
|
<div class="card card-neon h-100">
|
||||||
|
<div class="card-body d-flex flex-column">
|
||||||
|
<h5 class="card-title"><?php echo htmlspecialchars($community['name']); ?></h5>
|
||||||
|
<p class="card-text">Explore and engage with your local community.</p>
|
||||||
|
<div class="mt-auto">
|
||||||
|
<a href="discussions.php?community_id=<?php echo $community['id']; ?>" class="btn btn-primary btn-sm">Discussions</a>
|
||||||
|
<a href="proposals.php?community_id=<?php echo $community['id']; ?>" class="btn btn-secondary btn-sm">Proposals</a>
|
||||||
|
<a href="events.php?community_id=<?php echo $community['id']; ?>" class="btn btn-info btn-sm">Events</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
|
||||||
|
<footer class="bg-dark text-white text-center p-3 mt-auto">
|
||||||
|
<p>© <?php echo date("Y"); ?> Community Hub. All Rights Reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
22
db/migrate.php
Normal file
22
db/migrate.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/config.php';
|
||||||
|
|
||||||
|
function run_migrations() {
|
||||||
|
$pdo = db();
|
||||||
|
$migrations_dir = __DIR__ . '/migrations';
|
||||||
|
$files = glob($migrations_dir . '/*.sql');
|
||||||
|
sort($files);
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$sql = file_get_contents($file);
|
||||||
|
try {
|
||||||
|
$pdo->exec($sql);
|
||||||
|
echo "Migration successful: " . basename($file) . "\n";
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
echo "Migration failed for " . basename($file) . ": " . $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run_migrations();
|
||||||
|
|
||||||
10
db/migrations/001_create_users_table.sql
Normal file
10
db/migrations/001_create_users_table.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `users` (
|
||||||
|
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
`name` VARCHAR(255) NOT NULL,
|
||||||
|
`email` VARCHAR(255) NOT NULL UNIQUE,
|
||||||
|
`password` VARCHAR(255) NOT NULL,
|
||||||
|
`city` VARCHAR(255) NOT NULL,
|
||||||
|
`role` ENUM('member', 'leader') NOT NULL DEFAULT 'member',
|
||||||
|
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
8
db/migrations/002_create_communities_table.sql
Normal file
8
db/migrations/002_create_communities_table.sql
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `communities` (
|
||||||
|
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
`name` VARCHAR(255) NOT NULL UNIQUE,
|
||||||
|
`leader_id` INT NOT NULL,
|
||||||
|
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (`leader_id`) REFERENCES `users`(`id`)
|
||||||
|
);
|
||||||
9
db/migrations/003_create_community_members_table.sql
Normal file
9
db/migrations/003_create_community_members_table.sql
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `community_members` (
|
||||||
|
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
`user_id` INT NOT NULL,
|
||||||
|
`community_id` INT NOT NULL,
|
||||||
|
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`),
|
||||||
|
FOREIGN KEY (`community_id`) REFERENCES `communities`(`id`)
|
||||||
|
);
|
||||||
21
db/migrations/004_create_discussions_table.sql
Normal file
21
db/migrations/004_create_discussions_table.sql
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `discussions` (
|
||||||
|
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
`community_id` INT NOT NULL,
|
||||||
|
`user_id` INT NOT NULL,
|
||||||
|
`title` VARCHAR(255) NOT NULL,
|
||||||
|
`content` TEXT NOT NULL,
|
||||||
|
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (`community_id`) REFERENCES `communities`(`id`),
|
||||||
|
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `discussion_replies` (
|
||||||
|
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
`discussion_id` INT NOT NULL,
|
||||||
|
`user_id` INT NOT NULL,
|
||||||
|
`content` TEXT NOT NULL,
|
||||||
|
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (`discussion_id`) REFERENCES `discussions`(`id`),
|
||||||
|
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)
|
||||||
|
);
|
||||||
24
db/migrations/005_create_proposals_table.sql
Normal file
24
db/migrations/005_create_proposals_table.sql
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `proposals` (
|
||||||
|
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
`community_id` INT NOT NULL,
|
||||||
|
`user_id` INT NOT NULL,
|
||||||
|
`title` VARCHAR(255) NOT NULL,
|
||||||
|
`description` TEXT NOT NULL,
|
||||||
|
`end_time` TIMESTAMP NOT NULL,
|
||||||
|
`status` ENUM('active', 'resolved') NOT NULL DEFAULT 'active',
|
||||||
|
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (`community_id`) REFERENCES `communities`(`id`),
|
||||||
|
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `proposal_votes` (
|
||||||
|
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
`proposal_id` INT NOT NULL,
|
||||||
|
`user_id` INT NOT NULL,
|
||||||
|
`vote` ENUM('up', 'down') NOT NULL,
|
||||||
|
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
UNIQUE KEY `user_proposal_vote` (`user_id`, `proposal_id`),
|
||||||
|
FOREIGN KEY (`proposal_id`) REFERENCES `proposals`(`id`),
|
||||||
|
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)
|
||||||
|
);
|
||||||
25
db/migrations/006_create_events_table.sql
Normal file
25
db/migrations/006_create_events_table.sql
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `events` (
|
||||||
|
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
`community_id` INT NOT NULL,
|
||||||
|
`user_id` INT NOT NULL,
|
||||||
|
`title` VARCHAR(255) NOT NULL,
|
||||||
|
`description` TEXT NOT NULL,
|
||||||
|
`start_time` TIMESTAMP NOT NULL,
|
||||||
|
`end_time` TIMESTAMP NOT NULL,
|
||||||
|
`location` VARCHAR(255) NOT NULL,
|
||||||
|
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (`community_id`) REFERENCES `communities`(`id`),
|
||||||
|
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `event_rsvps` (
|
||||||
|
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
`event_id` INT NOT NULL,
|
||||||
|
`user_id` INT NOT NULL,
|
||||||
|
`rsvp` ENUM('attending', 'not_attending') NOT NULL,
|
||||||
|
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
UNIQUE KEY `user_event_rsvp` (`user_id`, `event_id`),
|
||||||
|
FOREIGN KEY (`event_id`) REFERENCES `events`(`id`),
|
||||||
|
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)
|
||||||
|
);
|
||||||
11
db/migrations/007_create_messages_table.sql
Normal file
11
db/migrations/007_create_messages_table.sql
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `messages` (
|
||||||
|
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
`sender_id` INT NOT NULL,
|
||||||
|
`recipient_id` INT NOT NULL,
|
||||||
|
`content` TEXT NOT NULL,
|
||||||
|
`is_read` BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (`sender_id`) REFERENCES `users`(`id`),
|
||||||
|
FOREIGN KEY (`recipient_id`) REFERENCES `users`(`id`)
|
||||||
|
);
|
||||||
51
delete_discussion.php
Normal file
51
delete_discussion.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($_GET['id'])) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$discussion_id = $_GET['id'];
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// Fetch discussion to get community_id and user_id
|
||||||
|
$stmt = $pdo->prepare('SELECT community_id, user_id FROM discussions WHERE id = ?');
|
||||||
|
$stmt->execute([$discussion_id]);
|
||||||
|
$discussion = $stmt->fetch();
|
||||||
|
|
||||||
|
if (!$discussion) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch user role
|
||||||
|
$stmt = $pdo->prepare('SELECT role FROM users WHERE id = ?');
|
||||||
|
$stmt->execute([$user_id]);
|
||||||
|
$user_role = $stmt->fetchColumn();
|
||||||
|
|
||||||
|
// Check if user is authorized to delete
|
||||||
|
if ($discussion['user_id'] != $user_id && $user_role != 'leader') {
|
||||||
|
header('Location: discussion.php?id=' . $discussion_id);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete replies first
|
||||||
|
$stmt = $pdo->prepare('DELETE FROM discussion_replies WHERE discussion_id = ?');
|
||||||
|
$stmt->execute([$discussion_id]);
|
||||||
|
|
||||||
|
// Delete discussion
|
||||||
|
$stmt = $pdo->prepare('DELETE FROM discussions WHERE id = ?');
|
||||||
|
$stmt->execute([$discussion_id]);
|
||||||
|
|
||||||
|
header('Location: discussions.php?community_id=' . $discussion['community_id']);
|
||||||
|
exit;
|
||||||
47
delete_reply.php
Normal file
47
delete_reply.php
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($_GET['id'])) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$reply_id = $_GET['id'];
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// Fetch reply to get discussion_id and user_id
|
||||||
|
$stmt = $pdo->prepare('SELECT discussion_id, user_id FROM discussion_replies WHERE id = ?');
|
||||||
|
$stmt->execute([$reply_id]);
|
||||||
|
$reply = $stmt->fetch();
|
||||||
|
|
||||||
|
if (!$reply) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch user role
|
||||||
|
$stmt = $pdo->prepare('SELECT role FROM users WHERE id = ?');
|
||||||
|
$stmt->execute([$user_id]);
|
||||||
|
$user_role = $stmt->fetchColumn();
|
||||||
|
|
||||||
|
// Check if user is authorized to delete
|
||||||
|
if ($reply['user_id'] != $user_id && $user_role != 'leader') {
|
||||||
|
header('Location: discussion.php?id=' . $reply['discussion_id']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete reply
|
||||||
|
$stmt = $pdo->prepare('DELETE FROM discussion_replies WHERE id = ?');
|
||||||
|
$stmt->execute([$reply_id]);
|
||||||
|
|
||||||
|
header('Location: discussion.php?id=' . $reply['discussion_id']);
|
||||||
|
exit;
|
||||||
162
discussion.php
Normal file
162
discussion.php
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($_GET['id'])) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$discussion_id = $_GET['id'];
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// Fetch discussion details
|
||||||
|
$stmt = $pdo->prepare('SELECT d.*, u.name as user_name, c.name as community_name, c.id as community_id FROM discussions d JOIN users u ON d.user_id = u.id JOIN communities c ON d.community_id = c.id WHERE d.id = ?');
|
||||||
|
$stmt->execute([$discussion_id]);
|
||||||
|
$discussion = $stmt->fetch();
|
||||||
|
|
||||||
|
if (!$discussion) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch user role in the community
|
||||||
|
$stmt = $pdo->prepare('SELECT role FROM users WHERE id = ?');
|
||||||
|
$stmt->execute([$user_id]);
|
||||||
|
$user_role = $stmt->fetchColumn();
|
||||||
|
|
||||||
|
// Handle new reply form submission
|
||||||
|
$content = '';
|
||||||
|
$errors = [];
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['content'])) {
|
||||||
|
$content = trim($_POST['content']);
|
||||||
|
|
||||||
|
if (empty($content)) {
|
||||||
|
$errors[] = 'Reply content cannot be empty';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($errors)) {
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare('INSERT INTO discussion_replies (discussion_id, user_id, content) VALUES (?, ?, ?)');
|
||||||
|
$stmt->execute([$discussion_id, $user_id, $content]);
|
||||||
|
header('Location: discussion.php?id=' . $discussion_id);
|
||||||
|
exit;
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$errors[] = 'Database error: ' . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch replies
|
||||||
|
$stmt = $pdo->prepare('SELECT dr.*, u.name as user_name FROM discussion_replies dr JOIN users u ON dr.user_id = u.id WHERE dr.discussion_id = ? ORDER BY dr.created_at ASC');
|
||||||
|
$stmt->execute([$discussion_id]);
|
||||||
|
$replies = $stmt->fetchAll();
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title><?php echo htmlspecialchars($discussion['title']); ?> - Community Hub</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
</head>
|
||||||
|
<body class="d-flex flex-column min-vh-100">
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="navbar-brand" href="index.php">Community Hub</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<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="index.php">Home</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="communities.php">Communities</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="profile.php">Profile</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="messages.php">Messages</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main class="flex-grow-1">
|
||||||
|
<section class="container mt-5">
|
||||||
|
<div class="card card-neon mb-4">
|
||||||
|
<div class="card-header">
|
||||||
|
<h1 class="mb-0"><?php echo htmlspecialchars($discussion['title']); ?></h1>
|
||||||
|
<small>in <a href="discussions.php?community_id=<?php echo $discussion['community_id']; ?>"><?php echo htmlspecialchars($discussion['community_name']); ?></a> by <?php echo htmlspecialchars($discussion['user_name']); ?> on <?php echo date('M j, Y, g:i a', strtotime($discussion['created_at'])); ?></small>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p><?php echo nl2br(htmlspecialchars($discussion['content'])); ?></p>
|
||||||
|
<?php if ($discussion['user_id'] == $user_id || $user_role == 'leader'): ?>
|
||||||
|
<div class="mt-3">
|
||||||
|
<a href="edit_discussion.php?id=<?php echo $discussion['id']; ?>" class="btn btn-secondary btn-sm">Edit</a>
|
||||||
|
<a href="delete_discussion.php?id=<?php echo $discussion['id']; ?>" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure you want to delete this discussion?');">Delete</a>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Replies</h2>
|
||||||
|
<div class="mb-4">
|
||||||
|
<?php if (empty($replies)): ?>
|
||||||
|
<p>No replies yet. Be the first to reply!</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php foreach ($replies as $reply): ?>
|
||||||
|
<div class="card card-neon mb-3">
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="mb-1"><?php echo nl2br(htmlspecialchars($reply['content'])); ?></p>
|
||||||
|
<small>by <?php echo htmlspecialchars($reply['user_name']); ?> on <?php echo date('M j, Y, g:i a', strtotime($reply['created_at'])); ?></small>
|
||||||
|
<?php if ($reply['user_id'] == $user_id || $user_role == 'leader'): ?>
|
||||||
|
<div class="mt-2">
|
||||||
|
<a href="edit_reply.php?id=<?php echo $reply['id']; ?>" class="btn btn-secondary btn-sm">Edit</a>
|
||||||
|
<a href="delete_reply.php?id=<?php echo $reply['id']; ?>" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure you want to delete this reply?');">Delete</a>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-neon">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title">Post a Reply</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="discussion.php?id=<?php echo $discussion_id; ?>" method="POST">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="content" class="form-label">Your Reply</label>
|
||||||
|
<textarea class="form-control" id="content" name="content" rows="3" required><?php echo htmlspecialchars($content); ?></textarea>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary btn-gradient">Post Reply</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="bg-dark text-white text-center p-3 mt-auto">
|
||||||
|
<p>© <?php echo date("Y"); ?> Community Hub. All Rights Reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
202
discussions.php
Normal file
202
discussions.php
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($_GET['community_id'])) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$community_id = $_GET['community_id'];
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// Fetch community details
|
||||||
|
$stmt = $pdo->prepare('SELECT * FROM communities WHERE id = ?');
|
||||||
|
$stmt->execute([$community_id]);
|
||||||
|
$community = $stmt->fetch();
|
||||||
|
|
||||||
|
if (!$community) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle new discussion form submission
|
||||||
|
$title = $content = '';
|
||||||
|
$errors = [];
|
||||||
|
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 {
|
||||||
|
$stmt = $pdo->prepare('INSERT INTO discussions (community_id, user_id, title, content) VALUES (?, ?, ?, ?)');
|
||||||
|
$stmt->execute([$community_id, $user_id, $title, $content]);
|
||||||
|
header('Location: discussions.php?community_id=' . $community_id);
|
||||||
|
exit;
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$errors[] = 'Database error: ' . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search
|
||||||
|
$search = isset($_GET['search']) ? trim($_GET['search']) : '';
|
||||||
|
|
||||||
|
// Pagination
|
||||||
|
$limit = 10;
|
||||||
|
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
|
||||||
|
$offset = ($page - 1) * $limit;
|
||||||
|
|
||||||
|
// Build where clause for search
|
||||||
|
$where_clause = 'WHERE d.community_id = ?';
|
||||||
|
$params = [$community_id];
|
||||||
|
if (!empty($search)) {
|
||||||
|
$where_clause .= ' AND (d.title LIKE ? OR d.content LIKE ?)';
|
||||||
|
$params[] = '%' . $search . '%';
|
||||||
|
$params[] = '%' . $search . '%';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch total number of discussions
|
||||||
|
$stmt = $pdo->prepare('SELECT COUNT(*) FROM discussions d ' . $where_clause);
|
||||||
|
$stmt->execute($params);
|
||||||
|
$total_discussions = $stmt->fetchColumn();
|
||||||
|
$total_pages = ceil($total_discussions / $limit);
|
||||||
|
|
||||||
|
// Fetch discussions for the current page
|
||||||
|
$sql = 'SELECT d.*, u.name as user_name FROM discussions d JOIN users u ON d.user_id = u.id ' . $where_clause . ' ORDER BY d.created_at DESC LIMIT ? OFFSET ?';
|
||||||
|
$stmt = $pdo->prepare($sql);
|
||||||
|
$params[] = $limit;
|
||||||
|
$params[] = $offset;
|
||||||
|
|
||||||
|
foreach ($params as $key => $value) {
|
||||||
|
$stmt->bindValue($key + 1, $value, is_int($value) ? PDO::PARAM_INT : PDO::PARAM_STR);
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt->execute();
|
||||||
|
$discussions = $stmt->fetchAll();
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title><?php echo htmlspecialchars($community['name']); ?> Discussions - Community Hub</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
</head>
|
||||||
|
<body class="d-flex flex-column min-vh-100">
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="navbar-brand" href="index.php">Community Hub</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<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="index.php">Home</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="communities.php">Communities</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="profile.php">Profile</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="messages.php">Messages</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main class="flex-grow-1">
|
||||||
|
<section class="container mt-5">
|
||||||
|
<h1 class="text-center mb-4">Discussions in <?php echo htmlspecialchars($community['name']); ?></h1>
|
||||||
|
|
||||||
|
<div class="card card-neon mb-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title">Start a New Discussion</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="discussions.php?community_id=<?php echo $community_id; ?>" 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="3" required><?php echo htmlspecialchars($content); ?></textarea>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary btn-gradient">Post Discussion</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="mb-3">Existing Discussions</h2>
|
||||||
|
|
||||||
|
<form action="discussions.php" method="GET" class="mb-4">
|
||||||
|
<input type="hidden" name="community_id" value="<?php echo $community_id; ?>">
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" class="form-control" placeholder="Search discussions..." name="search" value="<?php echo htmlspecialchars($search); ?>">
|
||||||
|
<button class="btn btn-outline-secondary" type="submit">Search</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="list-group">
|
||||||
|
<?php if (empty($discussions)): ?>
|
||||||
|
<p>No discussions found.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php foreach ($discussions as $discussion): ?>
|
||||||
|
<a href="discussion.php?id=<?php echo $discussion['id']; ?>" class="list-group-item list-group-item-action">
|
||||||
|
<div class="d-flex w-100 justify-content-between">
|
||||||
|
<h5 class="mb-1"><?php echo htmlspecialchars($discussion['title']); ?></h5>
|
||||||
|
<small><?php echo date('M j, Y, g:i a', strtotime($discussion['created_at'])); ?></small>
|
||||||
|
</div>
|
||||||
|
<p class="mb-1">Started by: <?php echo htmlspecialchars($discussion['user_name']); ?></p>
|
||||||
|
</a>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav aria-label="Page navigation">
|
||||||
|
<ul class="pagination justify-content-center mt-4">
|
||||||
|
<li class="page-item <?php echo ($page <= 1) ? 'disabled' : ''; ?>">
|
||||||
|
<a class="page-link" href="?community_id=<?php echo $community_id; ?>&page=<?php echo $page - 1; ?>&search=<?php echo urlencode($search); ?>">Previous</a>
|
||||||
|
</li>
|
||||||
|
<?php for ($i = 1; $i <= $total_pages; $i++): ?>
|
||||||
|
<li class="page-item <?php echo ($page == $i) ? 'active' : ''; ?>">
|
||||||
|
<a class="page-link" href="?community_id=<?php echo $community_id; ?>&page=<?php echo $i; ?>&search=<?php echo urlencode($search); ?>"><?php echo $i; ?></a>
|
||||||
|
</li>
|
||||||
|
<?php endfor; ?>
|
||||||
|
<li class="page-item <?php echo ($page >= $total_pages) ? 'disabled' : ''; ?>">
|
||||||
|
<a class="page-link" href="?community_id=<?php echo $community_id; ?>&page=<?php echo $page + 1; ?>&search=<?php echo urlencode($search); ?>">Next</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="bg-dark text-white text-center p-3 mt-auto">
|
||||||
|
<p>© <?php echo date("Y"); ?> Community Hub. All Rights Reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
135
edit_discussion.php
Normal file
135
edit_discussion.php
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($_GET['id'])) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$discussion_id = $_GET['id'];
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// Fetch discussion
|
||||||
|
$stmt = $pdo->prepare('SELECT * FROM discussions WHERE id = ?');
|
||||||
|
$stmt->execute([$discussion_id]);
|
||||||
|
$discussion = $stmt->fetch();
|
||||||
|
|
||||||
|
if (!$discussion) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch user role
|
||||||
|
$stmt = $pdo->prepare('SELECT role FROM users WHERE id = ?');
|
||||||
|
$stmt->execute([$user_id]);
|
||||||
|
$user_role = $stmt->fetchColumn();
|
||||||
|
|
||||||
|
// Check if user is authorized to edit
|
||||||
|
if ($discussion['user_id'] != $user_id && $user_role != 'leader') {
|
||||||
|
header('Location: discussion.php?id=' . $discussion_id);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$title = $discussion['title'];
|
||||||
|
$content = $discussion['content'];
|
||||||
|
$errors = [];
|
||||||
|
|
||||||
|
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 {
|
||||||
|
$stmt = $pdo->prepare('UPDATE discussions SET title = ?, content = ? WHERE id = ?');
|
||||||
|
$stmt->execute([$title, $content, $discussion_id]);
|
||||||
|
header('Location: discussion.php?id=' . $discussion_id);
|
||||||
|
exit;
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$errors[] = 'Database error: ' . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Edit Discussion - Community Hub</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
</head>
|
||||||
|
<body class="d-flex flex-column min-vh-100">
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="navbar-brand" href="index.php">Community Hub</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<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="index.php">Home</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="communities.php">Communities</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="profile.php">Profile</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="messages.php">Messages</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main class="flex-grow-1">
|
||||||
|
<section class="container mt-5">
|
||||||
|
<h1 class="text-center mb-4">Edit Discussion</h1>
|
||||||
|
<div class="card card-neon">
|
||||||
|
<div class="card-body">
|
||||||
|
<?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="edit_discussion.php?id=<?php echo $discussion_id; ?>" 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="5" required><?php echo htmlspecialchars($content); ?></textarea>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary btn-gradient">Save Changes</button>
|
||||||
|
<a href="discussion.php?id=<?php echo $discussion_id; ?>" class="btn btn-secondary">Cancel</a>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="bg-dark text-white text-center p-3 mt-auto">
|
||||||
|
<p>© <?php echo date("Y"); ?> Community Hub. All Rights Reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
126
edit_reply.php
Normal file
126
edit_reply.php
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($_GET['id'])) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$reply_id = $_GET['id'];
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// Fetch reply
|
||||||
|
$stmt = $pdo->prepare('SELECT * FROM discussion_replies WHERE id = ?');
|
||||||
|
$stmt->execute([$reply_id]);
|
||||||
|
$reply = $stmt->fetch();
|
||||||
|
|
||||||
|
if (!$reply) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch user role
|
||||||
|
$stmt = $pdo->prepare('SELECT role FROM users WHERE id = ?');
|
||||||
|
$stmt->execute([$user_id]);
|
||||||
|
$user_role = $stmt->fetchColumn();
|
||||||
|
|
||||||
|
// Check if user is authorized to edit
|
||||||
|
if ($reply['user_id'] != $user_id && $user_role != 'leader') {
|
||||||
|
header('Location: discussion.php?id=' . $reply['discussion_id']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$content = $reply['content'];
|
||||||
|
$errors = [];
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$content = trim($_POST['content'] ?? '');
|
||||||
|
|
||||||
|
if (empty($content)) {
|
||||||
|
$errors[] = 'Content is required';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($errors)) {
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare('UPDATE discussion_replies SET content = ? WHERE id = ?');
|
||||||
|
$stmt->execute([$content, $reply_id]);
|
||||||
|
header('Location: discussion.php?id=' . $reply['discussion_id']);
|
||||||
|
exit;
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$errors[] = 'Database error: ' . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Edit Reply - Community Hub</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
</head>
|
||||||
|
<body class="d-flex flex-column min-vh-100">
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="navbar-brand" href="index.php">Community Hub</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<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="index.php">Home</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="communities.php">Communities</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="profile.php">Profile</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="messages.php">Messages</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main class="flex-grow-1">
|
||||||
|
<section class="container mt-5">
|
||||||
|
<h1 class="text-center mb-4">Edit Reply</h1>
|
||||||
|
<div class="card card-neon">
|
||||||
|
<div class="card-body">
|
||||||
|
<?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="edit_reply.php?id=<?php echo $reply_id; ?>" method="POST">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="content" class="form-label">Content</label>
|
||||||
|
<textarea class="form-control" id="content" name="content" rows="5" required><?php echo htmlspecialchars($content); ?></textarea>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary btn-gradient">Save Changes</button>
|
||||||
|
<a href="discussion.php?id=<?php echo $reply['discussion_id']; ?>" class="btn btn-secondary">Cancel</a>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="bg-dark text-white text-center p-3 mt-auto">
|
||||||
|
<p>© <?php echo date("Y"); ?> Community Hub. All Rights Reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
150
event.php
Normal file
150
event.php
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($_GET['id'])) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$event_id = $_GET['id'];
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// Fetch event details
|
||||||
|
$stmt = $pdo->prepare('SELECT e.*, u.name as user_name, c.name as community_name FROM events e JOIN users u ON e.user_id = u.id JOIN communities c ON e.community_id = c.id WHERE e.id = ?');
|
||||||
|
$stmt->execute([$event_id]);
|
||||||
|
$event = $stmt->fetch();
|
||||||
|
|
||||||
|
if (!$event) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle RSVP
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['rsvp'])) {
|
||||||
|
$rsvp = $_POST['rsvp'];
|
||||||
|
if (in_array($rsvp, ['attending', 'not_attending'])) {
|
||||||
|
try {
|
||||||
|
// Check if user has already RSVPed
|
||||||
|
$stmt = $pdo->prepare('SELECT id FROM event_rsvps WHERE user_id = ? AND event_id = ?');
|
||||||
|
$stmt->execute([$user_id, $event_id]);
|
||||||
|
if ($stmt->fetch()) {
|
||||||
|
// Update existing RSVP
|
||||||
|
$stmt = $pdo->prepare('UPDATE event_rsvps SET rsvp = ? WHERE user_id = ? AND event_id = ?');
|
||||||
|
$stmt->execute([$rsvp, $user_id, $event_id]);
|
||||||
|
} else {
|
||||||
|
// Insert new RSVP
|
||||||
|
$stmt = $pdo->prepare('INSERT INTO event_rsvps (event_id, user_id, rsvp) VALUES (?, ?, ?)');
|
||||||
|
$stmt->execute([$event_id, $user_id, $rsvp]);
|
||||||
|
}
|
||||||
|
header('Location: event.php?id=' . $event_id);
|
||||||
|
exit;
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$errors[] = 'Database error: ' . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch RSVPs
|
||||||
|
$stmt = $pdo->prepare('SELECT rsvp, COUNT(*) as count FROM event_rsvps WHERE event_id = ? GROUP BY rsvp');
|
||||||
|
$stmt->execute([$event_id]);
|
||||||
|
$rsvps = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
|
||||||
|
|
||||||
|
$attending = $rsvps['attending'] ?? 0;
|
||||||
|
$not_attending = $rsvps['not_attending'] ?? 0;
|
||||||
|
|
||||||
|
// Check if the current user has RSVPed
|
||||||
|
$stmt = $pdo->prepare('SELECT rsvp FROM event_rsvps WHERE user_id = ? AND event_id = ?');
|
||||||
|
$stmt->execute([$user_id, $event_id]);
|
||||||
|
$user_rsvp = $stmt->fetchColumn();
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title><?php echo htmlspecialchars($event['title']); ?> - Community Hub</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
</head>
|
||||||
|
<body class="d-flex flex-column min-vh-100">
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="navbar-brand" href="index.php">Community Hub</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<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="index.php">Home</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="communities.php">Communities</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="profile.php">Profile</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="messages.php">Messages</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main class="flex-grow-1">
|
||||||
|
<section class="container mt-5">
|
||||||
|
<div class="card card-neon mb-4">
|
||||||
|
<div class="card-header">
|
||||||
|
<h1 class="mb-0"><?php echo htmlspecialchars($event['title']); ?></h1>
|
||||||
|
<small>in <a href="discussions.php?community_id=<?php echo $event['community_id']; ?>"><?php echo htmlspecialchars($event['community_name']); ?></a> by <?php echo htmlspecialchars($event['user_name']); ?> on <?php echo date('M j, Y, g:i a', strtotime($event['created_at'])); ?></small>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p><?php echo nl2br(htmlspecialchars($event['description'])); ?></p>
|
||||||
|
<p><strong>Starts:</strong> <?php echo date('M j, Y, g:i a', strtotime($event['start_time'])); ?></p>
|
||||||
|
<p><strong>Ends:</strong> <?php echo date('M j, Y, g:i a', strtotime($event['end_time'])); ?></p>
|
||||||
|
<p><strong>Location:</strong> <?php echo htmlspecialchars($event['location']); ?></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>RSVPs</h2>
|
||||||
|
<div class="d-flex justify-content-around mb-4">
|
||||||
|
<div class="text-center">
|
||||||
|
<h3>Attending</h3>
|
||||||
|
<p class="display-4"><?php echo $attending; ?></p>
|
||||||
|
</div>
|
||||||
|
<div class="text-center">
|
||||||
|
<h3>Not Attending</h3>
|
||||||
|
<p class="display-4"><?php echo $not_attending; ?></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-neon">
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<h2 class="card-title">RSVP</h2>
|
||||||
|
<form action="event.php?id=<?php echo $event_id; ?>" method="POST" class="d-inline">
|
||||||
|
<input type="hidden" name="rsvp" value="attending">
|
||||||
|
<button type="submit" class="btn btn-success btn-lg me-2 <?php echo ($user_rsvp === 'attending') ? 'active' : ''; ?>">Attending</button>
|
||||||
|
</form>
|
||||||
|
<form action="event.php?id=<?php echo $event_id; ?>" method="POST" class="d-inline">
|
||||||
|
<input type="hidden" name="rsvp" value="not_attending">
|
||||||
|
<button type="submit" class="btn btn-danger btn-lg <?php echo ($user_rsvp === 'not_attending') ? 'active' : ''; ?>">Not Attending</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="bg-dark text-white text-center p-3 mt-auto">
|
||||||
|
<p>© <?php echo date("Y"); ?> Community Hub. All Rights Reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
173
events.php
Normal file
173
events.php
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($_GET['community_id'])) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$community_id = $_GET['community_id'];
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// Fetch community details
|
||||||
|
$stmt = $pdo->prepare('SELECT * FROM communities WHERE id = ?');
|
||||||
|
$stmt->execute([$community_id]);
|
||||||
|
$community = $stmt->fetch();
|
||||||
|
|
||||||
|
if (!$community) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle new event form submission
|
||||||
|
$title = $description = $start_time = $end_time = $location = '';
|
||||||
|
$errors = [];
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$title = trim($_POST['title'] ?? '');
|
||||||
|
$description = trim($_POST['description'] ?? '');
|
||||||
|
$start_time = trim($_POST['start_time'] ?? '');
|
||||||
|
$end_time = trim($_POST['end_time'] ?? '');
|
||||||
|
$location = trim($_POST['location'] ?? '');
|
||||||
|
|
||||||
|
if (empty($title)) {
|
||||||
|
$errors[] = 'Title is required';
|
||||||
|
}
|
||||||
|
if (empty($description)) {
|
||||||
|
$errors[] = 'Description is required';
|
||||||
|
}
|
||||||
|
if (empty($start_time)) {
|
||||||
|
$errors[] = 'Start time is required';
|
||||||
|
}
|
||||||
|
if (empty($end_time)) {
|
||||||
|
$errors[] = 'End time is required';
|
||||||
|
}
|
||||||
|
if (empty($location)) {
|
||||||
|
$errors[] = 'Location is required';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($errors)) {
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare('INSERT INTO events (community_id, user_id, title, description, start_time, end_time, location) VALUES (?, ?, ?, ?, ?, ?, ?)');
|
||||||
|
$stmt->execute([$community_id, $user_id, $title, $description, $start_time, $end_time, $location]);
|
||||||
|
header('Location: events.php?community_id=' . $community_id);
|
||||||
|
exit;
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$errors[] = 'Database error: ' . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch events
|
||||||
|
$stmt = $pdo->prepare('SELECT e.*, u.name as user_name FROM events e JOIN users u ON e.user_id = u.id WHERE e.community_id = ? ORDER BY e.start_time DESC');
|
||||||
|
$stmt->execute([$community_id]);
|
||||||
|
$events = $stmt->fetchAll();
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title><?php echo htmlspecialchars($community['name']); ?> Events - Community Hub</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
</head>
|
||||||
|
<body class="d-flex flex-column min-vh-100">
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="navbar-brand" href="index.php">Community Hub</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<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="index.php">Home</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="communities.php">Communities</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="profile.php">Profile</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="messages.php">Messages</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main class="flex-grow-1">
|
||||||
|
<section class="container mt-5">
|
||||||
|
<h1 class="text-center mb-4">Events in <?php echo htmlspecialchars($community['name']); ?></h1>
|
||||||
|
|
||||||
|
<div class="card card-neon mb-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title">Create a New Event</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="events.php?community_id=<?php echo $community_id; ?>" 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="description" class="form-label">Description</label>
|
||||||
|
<textarea class="form-control" id="description" name="description" rows="3" required><?php echo htmlspecialchars($description); ?></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label for="start_time" class="form-label">Start Time</label>
|
||||||
|
<input type="datetime-local" class="form-control" id="start_time" name="start_time" value="<?php echo htmlspecialchars($start_time); ?>" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label for="end_time" class="form-label">End Time</label>
|
||||||
|
<input type="datetime-local" class="form-control" id="end_time" name="end_time" value="<?php echo htmlspecialchars($end_time); ?>" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="location" class="form-label">Location</label>
|
||||||
|
<input type="text" class="form-control" id="location" name="location" value="<?php echo htmlspecialchars($location); ?>" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary btn-gradient">Create Event</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Upcoming Events</h2>
|
||||||
|
<div class="list-group">
|
||||||
|
<?php if (empty($events)): ?>
|
||||||
|
<p>No events yet. Be the first to create one!</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php foreach ($events as $event): ?>
|
||||||
|
<a href="event.php?id=<?php echo $event['id']; ?>" class="list-group-item list-group-item-action">
|
||||||
|
<div class="d-flex w-100 justify-content-between">
|
||||||
|
<h5 class="mb-1"><?php echo htmlspecialchars($event['title']); ?></h5>
|
||||||
|
<small><?php echo date('M j, Y, g:i a', strtotime($event['start_time'])); ?></small>
|
||||||
|
</div>
|
||||||
|
<p class="mb-1">Location: <?php echo htmlspecialchars($event['location']); ?></p>
|
||||||
|
<p class="mb-1">Created by: <?php echo htmlspecialchars($event['user_name']); ?></p>
|
||||||
|
</a>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="bg-dark text-white text-center p-3 mt-auto">
|
||||||
|
<p>© <?php echo date("Y"); ?> Community Hub. All Rights Reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
221
index.php
221
index.php
@ -1,150 +1,83 @@
|
|||||||
<?php
|
|
||||||
declare(strict_types=1);
|
|
||||||
@ini_set('display_errors', '1');
|
|
||||||
@error_reporting(E_ALL);
|
|
||||||
@date_default_timezone_set('UTC');
|
|
||||||
|
|
||||||
$phpVersion = PHP_VERSION;
|
<?php session_start(); ?>
|
||||||
$now = date('Y-m-d H:i:s');
|
<!DOCTYPE html>
|
||||||
?>
|
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>New Style</title>
|
<title>Community Hub</title>
|
||||||
<?php
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
// Read project preview data from environment
|
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&family=Roboto:wght@400;700&display=swap" rel="stylesheet">
|
||||||
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
|
||||||
?>
|
|
||||||
<?php if ($projectDescription): ?>
|
|
||||||
<!-- Meta description -->
|
|
||||||
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
|
|
||||||
<!-- Open Graph meta tags -->
|
|
||||||
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
|
||||||
<!-- Twitter meta tags -->
|
|
||||||
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if ($projectImageUrl): ?>
|
|
||||||
<!-- Open Graph image -->
|
|
||||||
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
|
||||||
<!-- Twitter image -->
|
|
||||||
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
|
||||||
<?php endif; ?>
|
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
|
|
||||||
<style>
|
|
||||||
:root {
|
|
||||||
--bg-color-start: #6a11cb;
|
|
||||||
--bg-color-end: #2575fc;
|
|
||||||
--text-color: #ffffff;
|
|
||||||
--card-bg-color: rgba(255, 255, 255, 0.01);
|
|
||||||
--card-border-color: rgba(255, 255, 255, 0.1);
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
font-family: 'Inter', sans-serif;
|
|
||||||
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
|
|
||||||
color: var(--text-color);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
min-height: 100vh;
|
|
||||||
text-align: center;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
body::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
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>');
|
|
||||||
animation: bg-pan 20s linear infinite;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
@keyframes bg-pan {
|
|
||||||
0% { background-position: 0% 0%; }
|
|
||||||
100% { background-position: 100% 100%; }
|
|
||||||
}
|
|
||||||
main {
|
|
||||||
padding: 2rem;
|
|
||||||
}
|
|
||||||
.card {
|
|
||||||
background: var(--card-bg-color);
|
|
||||||
border: 1px solid var(--card-border-color);
|
|
||||||
border-radius: 16px;
|
|
||||||
padding: 2rem;
|
|
||||||
backdrop-filter: blur(20px);
|
|
||||||
-webkit-backdrop-filter: blur(20px);
|
|
||||||
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
.loader {
|
|
||||||
margin: 1.25rem auto 1.25rem;
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
border: 3px solid rgba(255, 255, 255, 0.25);
|
|
||||||
border-top-color: #fff;
|
|
||||||
border-radius: 50%;
|
|
||||||
animation: spin 1s linear infinite;
|
|
||||||
}
|
|
||||||
@keyframes spin {
|
|
||||||
from { transform: rotate(0deg); }
|
|
||||||
to { transform: rotate(360deg); }
|
|
||||||
}
|
|
||||||
.hint {
|
|
||||||
opacity: 0.9;
|
|
||||||
}
|
|
||||||
.sr-only {
|
|
||||||
position: absolute;
|
|
||||||
width: 1px; height: 1px;
|
|
||||||
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>
|
</head>
|
||||||
<body>
|
<body class="d-flex flex-column min-vh-100">
|
||||||
<main>
|
|
||||||
<div class="card">
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
<h1>Analyzing your requirements and generating your website…</h1>
|
<div class="container-fluid">
|
||||||
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
|
<a class="navbar-brand" href="index.php">Community Hub</a>
|
||||||
<span class="sr-only">Loading…</span>
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
</div>
|
<span class="navbar-toggler-icon"></span>
|
||||||
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
|
</button>
|
||||||
<p class="hint">This page will update automatically as the plan is implemented.</p>
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
|
<ul class="navbar-nav ms-auto">
|
||||||
|
<li class="nav-item"><a class="nav-link active" aria-current="page" href="index.php">Home</a></li>
|
||||||
|
<?php if (isset($_SESSION['user_id'])): ?>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="communities.php">Communities</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="profile.php">Profile</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="messages.php">Messages</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
|
||||||
|
<?php else: ?>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="login.php">Login</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="signup.php">Sign Up</a></li>
|
||||||
|
<?php endif; ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</nav>
|
||||||
<footer>
|
|
||||||
Page updated: <?= htmlspecialchars($now) ?> (UTC)
|
<main class="flex-grow-1">
|
||||||
</footer>
|
<header class="hero text-white text-center">
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="display-4">Build Your Community. Shape Your City.</h1>
|
||||||
|
<p class="lead">The platform where neighbors connect, leaders emerge, and real change starts with one discussion.</p>
|
||||||
|
<a href="signup.php" class="btn btn-primary btn-gradient me-2">Join Your City</a>
|
||||||
|
<a href="communities.php" class="btn btn-secondary">Explore Communities</a>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="features text-center py-5">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="feature-icon mb-3">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-users"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M23 21v-2a4 4 0 0 0-3-3.87"></path><path d="M16 3.13a4 4 0 0 1 0 7.75"></path></svg>
|
||||||
|
</div>
|
||||||
|
<h3>Connect</h3>
|
||||||
|
<p class="text-muted">Join communities in your city and connect with your neighbors.</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="feature-icon mb-3">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-message-square"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>
|
||||||
|
</div>
|
||||||
|
<h3>Discuss</h3>
|
||||||
|
<p class="text-muted">Start and participate in discussions about topics that matter to you.</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="feature-icon mb-3">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-trending-up"><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"></polyline><polyline points="17 6 23 6 23 12"></polyline></svg>
|
||||||
|
</div>
|
||||||
|
<h3>Organize</h3>
|
||||||
|
<p class="text-muted">Create events and proposals to drive real change in your community.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="bg-dark text-white text-center p-3 mt-auto">
|
||||||
|
<p>© <?php echo date("Y"); ?> Community Hub. All Rights Reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
117
login.php
Normal file
117
login.php
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
$email = $password = '';
|
||||||
|
$errors = [];
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$email = trim($_POST['email'] ?? '');
|
||||||
|
$password = $_POST['password'] ?? '';
|
||||||
|
|
||||||
|
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
$errors[] = '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'];
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
$errors[] = 'Invalid email or password';
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$errors[] = 'Database error: ' . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Login - Community Hub</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
</head>
|
||||||
|
<body class="d-flex flex-column min-vh-100">
|
||||||
|
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="navbar-brand" href="index.php">Community Hub</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<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="index.php">Home</a></li>
|
||||||
|
<?php if (isset($_SESSION['user_id'])): ?>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="communities.php">Communities</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="profile.php">Profile</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="messages.php">Messages</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
|
||||||
|
<?php else: ?>
|
||||||
|
<li class="nav-item"><a class="nav-link active" aria-current="page" href="login.php">Login</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="signup.php">Sign Up</a></li>
|
||||||
|
<?php endif; ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
|
<main class="flex-grow-1">
|
||||||
|
<section class="container mt-5">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card card-neon">
|
||||||
|
<div class="card-body">
|
||||||
|
<h1 class="text-center mb-4">Login to Your Account</h1>
|
||||||
|
<?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>
|
||||||
|
<div class="d-grid">
|
||||||
|
<button type="submit" class="btn btn-primary btn-gradient">Login</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="bg-dark text-white text-center p-3 mt-auto">
|
||||||
|
<p>© <?php echo date("Y"); ?> Community Hub. All Rights Reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
7
logout.php
Normal file
7
logout.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
session_unset();
|
||||||
|
session_destroy();
|
||||||
|
header('Location: index.php');
|
||||||
|
exit;
|
||||||
170
profile.php
Normal file
170
profile.php
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// Fetch user details
|
||||||
|
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
|
||||||
|
$stmt->execute([$user_id]);
|
||||||
|
$user = $stmt->fetch();
|
||||||
|
|
||||||
|
// Fetch user's communities
|
||||||
|
$stmt = $pdo->prepare('SELECT c.* FROM communities c JOIN community_members cm ON c.id = cm.community_id WHERE cm.user_id = ?');
|
||||||
|
$stmt->execute([$user_id]);
|
||||||
|
$communities = $stmt->fetchAll();
|
||||||
|
|
||||||
|
// Fetch user's discussions
|
||||||
|
$stmt = $pdo->prepare('SELECT * FROM discussions WHERE user_id = ? ORDER BY created_at DESC');
|
||||||
|
$stmt->execute([$user_id]);
|
||||||
|
$discussions = $stmt->fetchAll();
|
||||||
|
|
||||||
|
$name = $user['name'];
|
||||||
|
$city = $user['city'];
|
||||||
|
$errors = [];
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$name = trim($_POST['name'] ?? '');
|
||||||
|
$city = trim($_POST['city'] ?? '');
|
||||||
|
|
||||||
|
if (empty($name)) {
|
||||||
|
$errors[] = 'Name is required';
|
||||||
|
}
|
||||||
|
if (empty($city)) {
|
||||||
|
$errors[] = 'City is required';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($errors)) {
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare('UPDATE users SET name = ?, city = ? WHERE id = ?');
|
||||||
|
$stmt->execute([$name, $city, $user_id]);
|
||||||
|
header('Location: profile.php');
|
||||||
|
exit;
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$errors[] = 'Database error: ' . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Your Profile - Community Hub</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
</head>
|
||||||
|
<body class="d-flex flex-column min-vh-100">
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="navbar-brand" href="index.php">Community Hub</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<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="index.php">Home</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="communities.php">Communities</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link active" aria-current="page" href="profile.php">Profile</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="messages.php">Messages</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main class="flex-grow-1">
|
||||||
|
<section class="container mt-5">
|
||||||
|
<h1 class="text-center mb-4">Your Profile</h1>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card card-neon">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title">Your Information</h2>
|
||||||
|
<p><strong>Name:</strong> <?php echo htmlspecialchars($user['name']); ?></p>
|
||||||
|
<p><strong>Email:</strong> <?php echo htmlspecialchars($user['email']); ?></p>
|
||||||
|
<p><strong>City:</strong> <?php echo htmlspecialchars($user['city']); ?></p>
|
||||||
|
<p><strong>Role:</strong> <?php echo htmlspecialchars($user['role']); ?></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card card-neon mt-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title">Edit Profile</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="profile.php" method="POST">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="name" class="form-label">Name</label>
|
||||||
|
<input type="text" class="form-control" id="name" name="name" value="<?php echo htmlspecialchars($name); ?>" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="city" class="form-label">City</label>
|
||||||
|
<input type="text" class="form-control" id="city" name="city" value="<?php echo htmlspecialchars($city); ?>" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary btn-gradient">Save Changes</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card card-neon">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title">Your Communities</h2>
|
||||||
|
<div class="list-group">
|
||||||
|
<?php if (empty($communities)): ?>
|
||||||
|
<p>You are not a member of any communities yet.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php foreach ($communities as $community): ?>
|
||||||
|
<a href="discussions.php?community_id=<?php echo $community['id']; ?>" class="list-group-item list-group-item-action">
|
||||||
|
<?php echo htmlspecialchars($community['name']); ?>
|
||||||
|
</a>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card card-neon mt-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title">Your Discussions</h2>
|
||||||
|
<div class="list-group">
|
||||||
|
<?php if (empty($discussions)): ?>
|
||||||
|
<p>You have not started any discussions yet.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php foreach ($discussions as $discussion): ?>
|
||||||
|
<a href="discussion.php?id=<?php echo $discussion['id']; ?>" class="list-group-item list-group-item-action">
|
||||||
|
<?php echo htmlspecialchars($discussion['title']); ?>
|
||||||
|
</a>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="bg-dark text-white text-center p-3 mt-auto">
|
||||||
|
<p>© <?php echo date("Y"); ?> Community Hub. All Rights Reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
152
proposal.php
Normal file
152
proposal.php
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($_GET['id'])) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$proposal_id = $_GET['id'];
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// Fetch proposal details
|
||||||
|
$stmt = $pdo->prepare('SELECT p.*, u.name as user_name, c.name as community_name FROM proposals p JOIN users u ON p.user_id = u.id JOIN communities c ON p.community_id = c.id WHERE p.id = ?');
|
||||||
|
$stmt->execute([$proposal_id]);
|
||||||
|
$proposal = $stmt->fetch();
|
||||||
|
|
||||||
|
if (!$proposal) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle voting
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['vote'])) {
|
||||||
|
$vote = $_POST['vote'];
|
||||||
|
if (in_array($vote, ['up', 'down'])) {
|
||||||
|
try {
|
||||||
|
// Check if user has already voted
|
||||||
|
$stmt = $pdo->prepare('SELECT id FROM proposal_votes WHERE user_id = ? AND proposal_id = ?');
|
||||||
|
$stmt->execute([$user_id, $proposal_id]);
|
||||||
|
if ($stmt->fetch()) {
|
||||||
|
// Update existing vote
|
||||||
|
$stmt = $pdo->prepare('UPDATE proposal_votes SET vote = ? WHERE user_id = ? AND proposal_id = ?');
|
||||||
|
$stmt->execute([$vote, $user_id, $proposal_id]);
|
||||||
|
} else {
|
||||||
|
// Insert new vote
|
||||||
|
$stmt = $pdo->prepare('INSERT INTO proposal_votes (proposal_id, user_id, vote) VALUES (?, ?, ?)');
|
||||||
|
$stmt->execute([$proposal_id, $user_id, $vote]);
|
||||||
|
}
|
||||||
|
header('Location: proposal.php?id=' . $proposal_id);
|
||||||
|
exit;
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$errors[] = 'Database error: ' . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch votes
|
||||||
|
$stmt = $pdo->prepare('SELECT vote, COUNT(*) as count FROM proposal_votes WHERE proposal_id = ? GROUP BY vote');
|
||||||
|
$stmt->execute([$proposal_id]);
|
||||||
|
$votes = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
|
||||||
|
|
||||||
|
$up_votes = $votes['up'] ?? 0;
|
||||||
|
$down_votes = $votes['down'] ?? 0;
|
||||||
|
|
||||||
|
// Check if the current user has voted
|
||||||
|
$stmt = $pdo->prepare('SELECT vote FROM proposal_votes WHERE user_id = ? AND proposal_id = ?');
|
||||||
|
$stmt->execute([$user_id, $proposal_id]);
|
||||||
|
$user_vote = $stmt->fetchColumn();
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title><?php echo htmlspecialchars($proposal['title']); ?> - Community Hub</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
</head>
|
||||||
|
<body class="d-flex flex-column min-vh-100">
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="navbar-brand" href="index.php">Community Hub</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<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="index.php">Home</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="communities.php">Communities</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="profile.php">Profile</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="messages.php">Messages</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main class="flex-grow-1">
|
||||||
|
<section class="container mt-5">
|
||||||
|
<div class="card card-neon mb-4">
|
||||||
|
<div class="card-header">
|
||||||
|
<h1 class="mb-0"><?php echo htmlspecialchars($proposal['title']); ?></h1>
|
||||||
|
<small>in <a href="discussions.php?community_id=<?php echo $proposal['community_id']; ?>"><?php echo htmlspecialchars($proposal['community_name']); ?></a> by <?php echo htmlspecialchars($proposal['user_name']); ?> on <?php echo date('M j, Y, g:i a', strtotime($proposal['created_at'])); ?></small>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p><?php echo nl2br(htmlspecialchars($proposal['description'])); ?></p>
|
||||||
|
<p><strong>Voting ends:</strong> <?php echo date('M j, Y, g:i a', strtotime($proposal['end_time'])); ?></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Voting</h2>
|
||||||
|
<div class="d-flex justify-content-around mb-4">
|
||||||
|
<div class="text-center">
|
||||||
|
<h3>Upvotes</h3>
|
||||||
|
<p class="display-4"><?php echo $up_votes; ?></p>
|
||||||
|
</div>
|
||||||
|
<div class="text-center">
|
||||||
|
<h3>Downvotes</h3>
|
||||||
|
<p class="display-4"><?php echo $down_votes; ?></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if (strtotime($proposal['end_time']) > time()): ?>
|
||||||
|
<div class="card card-neon">
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<h2 class="card-title">Cast Your Vote</h2>
|
||||||
|
<form action="proposal.php?id=<?php echo $proposal_id; ?>" method="POST" class="d-inline">
|
||||||
|
<input type="hidden" name="vote" value="up">
|
||||||
|
<button type="submit" class="btn btn-success btn-lg me-2 <?php echo ($user_vote === 'up') ? 'active' : ''; ?>">Vote Up</button>
|
||||||
|
</form>
|
||||||
|
<form action="proposal.php?id=<?php echo $proposal_id; ?>" method="POST" class="d-inline">
|
||||||
|
<input type="hidden" name="vote" value="down">
|
||||||
|
<button type="submit" class="btn btn-danger btn-lg <?php echo ($user_vote === 'down') ? 'active' : ''; ?>">Vote Down</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="alert alert-info text-center">Voting on this proposal has ended.</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="bg-dark text-white text-center p-3 mt-auto">
|
||||||
|
<p>© <?php echo date("Y"); ?> Community Hub. All Rights Reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
161
proposals.php
Normal file
161
proposals.php
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($_GET['community_id'])) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$community_id = $_GET['community_id'];
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// Fetch community details
|
||||||
|
$stmt = $pdo->prepare('SELECT * FROM communities WHERE id = ?');
|
||||||
|
$stmt->execute([$community_id]);
|
||||||
|
$community = $stmt->fetch();
|
||||||
|
|
||||||
|
if (!$community) {
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch user role
|
||||||
|
$stmt = $pdo->prepare('SELECT role FROM users WHERE id = ?');
|
||||||
|
$stmt->execute([$user_id]);
|
||||||
|
$user_role = $stmt->fetchColumn();
|
||||||
|
|
||||||
|
// Handle new proposal form submission
|
||||||
|
$title = $description = $end_time = '';
|
||||||
|
$errors = [];
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $user_role === 'leader') {
|
||||||
|
$title = trim($_POST['title'] ?? '');
|
||||||
|
$description = trim($_POST['description'] ?? '');
|
||||||
|
$end_time = trim($_POST['end_time'] ?? '');
|
||||||
|
|
||||||
|
if (empty($title)) {
|
||||||
|
$errors[] = 'Title is required';
|
||||||
|
}
|
||||||
|
if (empty($description)) {
|
||||||
|
$errors[] = 'Description is required');
|
||||||
|
}
|
||||||
|
if (empty($end_time)) {
|
||||||
|
$errors[] = 'End time is required';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($errors)) {
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare('INSERT INTO proposals (community_id, user_id, title, description, end_time) VALUES (?, ?, ?, ?, ?)');
|
||||||
|
$stmt->execute([$community_id, $user_id, $title, $description, $end_time]);
|
||||||
|
header('Location: proposals.php?community_id=' . $community_id);
|
||||||
|
exit;
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$errors[] = 'Database error: ' . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch proposals
|
||||||
|
$stmt = $pdo->prepare('SELECT p.*, u.name as user_name FROM proposals p JOIN users u ON p.user_id = u.id WHERE p.community_id = ? ORDER BY p.created_at DESC');
|
||||||
|
$stmt->execute([$community_id]);
|
||||||
|
$proposals = $stmt->fetchAll();
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title><?php echo htmlspecialchars($community['name']); ?> Proposals - Community Hub</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
</head>
|
||||||
|
<body class="d-flex flex-column min-vh-100">
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="navbar-brand" href="index.php">Community Hub</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<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="index.php">Home</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="communities.php">Communities</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="profile.php">Profile</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="messages.php">Messages</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main class="flex-grow-1">
|
||||||
|
<section class="container mt-5">
|
||||||
|
<h1 class="text-center mb-4">Proposals in <?php echo htmlspecialchars($community['name']); ?></h1>
|
||||||
|
|
||||||
|
<?php if ($user_role === 'leader'): ?>
|
||||||
|
<div class="card card-neon mb-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title">Create a New Proposal</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="proposals.php?community_id=<?php echo $community_id; ?>" 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="description" class="form-label">Description</label>
|
||||||
|
<textarea class="form-control" id="description" name="description" rows="3" required><?php echo htmlspecialchars($description); ?></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="end_time" class="form-label">End Time</label>
|
||||||
|
<input type="datetime-local" class="form-control" id="end_time" name="end_time" value="<?php echo htmlspecialchars($end_time); ?>" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary btn-gradient">Create Proposal</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<h2>Active Proposals</h2>
|
||||||
|
<div class="list-group">
|
||||||
|
<?php if (empty($proposals)): ?>
|
||||||
|
<p>No proposals yet. <?php if ($user_role === 'leader'): ?>Be the first to create one!<?php endif; ?></p>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php foreach ($proposals as $proposal): ?>
|
||||||
|
<a href="proposal.php?id=<?php echo $proposal['id']; ?>" class="list-group-item list-group-item-action">
|
||||||
|
<div class="d-flex w-100 justify-content-between">
|
||||||
|
<h5 class="mb-1"><?php echo htmlspecialchars($proposal['title']); ?></h5>
|
||||||
|
<small>Ends <?php echo date('M j, Y, g:i a', strtotime($proposal['end_time'])); ?></small>
|
||||||
|
</div>
|
||||||
|
<p class="mb-1">Created by: <?php echo htmlspecialchars($proposal['user_name']); ?></p>
|
||||||
|
</a>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="bg-dark text-white text-center p-3 mt-auto">
|
||||||
|
<p>© <?php echo date("Y"); ?> Community Hub. All Rights Reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
188
signup.php
Normal file
188
signup.php
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
$name = $email = $password = $city = '';
|
||||||
|
$errors = [];
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$name = trim($_POST['name'] ?? '');
|
||||||
|
$email = trim($_POST['email'] ?? '');
|
||||||
|
$password = $_POST['password'] ?? '';
|
||||||
|
$city = trim($_POST['city'] ?? '');
|
||||||
|
|
||||||
|
if (empty($name)) {
|
||||||
|
$errors[] = 'Name is required';
|
||||||
|
}
|
||||||
|
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
$errors[] = 'Valid email is required';
|
||||||
|
}
|
||||||
|
if (empty($password)) {
|
||||||
|
$errors[] = 'Password is required';
|
||||||
|
}
|
||||||
|
if (empty($city)) {
|
||||||
|
$errors[] = 'City is required';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($errors)) {
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// Check if user already exists
|
||||||
|
$stmt = $pdo->prepare('SELECT id FROM users WHERE email = ?');
|
||||||
|
$stmt->execute([$email]);
|
||||||
|
if ($stmt->fetch()) {
|
||||||
|
$errors[] = 'User with this email already exists';
|
||||||
|
} else {
|
||||||
|
$pdo->beginTransaction();
|
||||||
|
|
||||||
|
// Check if community for the city exists
|
||||||
|
$stmt = $pdo->prepare('SELECT id FROM communities WHERE name = ?');
|
||||||
|
$stmt->execute([$city]);
|
||||||
|
$community = $stmt->fetch();
|
||||||
|
|
||||||
|
$role = 'member';
|
||||||
|
if (!$community) {
|
||||||
|
$role = 'leader';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert the new user
|
||||||
|
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
||||||
|
$stmt = $pdo->prepare('INSERT INTO users (name, email, password, city, role) VALUES (?, ?, ?, ?, ?)');
|
||||||
|
$stmt->execute([$name, $email, $hashed_password, $city, $role]);
|
||||||
|
$user_id = $pdo->lastInsertId();
|
||||||
|
|
||||||
|
if ($role === 'leader') {
|
||||||
|
$stmt = $pdo->prepare('INSERT INTO communities (name, leader_id) VALUES (?, ?)');
|
||||||
|
$stmt->execute([$city, $user_id]);
|
||||||
|
$community_id = $pdo->lastInsertId();
|
||||||
|
} else {
|
||||||
|
$community_id = $community['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add user to community
|
||||||
|
$stmt = $pdo->prepare('INSERT INTO community_members (user_id, community_id) VALUES (?, ?)');
|
||||||
|
$stmt->execute([$user_id, $community_id]);
|
||||||
|
|
||||||
|
$pdo->commit();
|
||||||
|
|
||||||
|
$_SESSION['user_id'] = $user_id;
|
||||||
|
header('Location: communities.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
if ($pdo->inTransaction()) {
|
||||||
|
$pdo->rollBack();
|
||||||
|
}
|
||||||
|
$errors[] = 'Database error: ' . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Sign Up - Community Hub</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
</head>
|
||||||
|
<body class="d-flex flex-column min-vh-100">
|
||||||
|
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="navbar-brand" href="index.php">Community Hub</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<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="index.php">Home</a></li>
|
||||||
|
<?php if (isset($_SESSION['user_id'])): ?>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="communities.php">Communities</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="profile.php">Profile</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="messages.php">Messages</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
|
||||||
|
<?php else: ?>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="login.php">Login</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link active" aria-current="page" href="signup.php">Sign Up</a></li>
|
||||||
|
<?php endif; ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
|
<main class="flex-grow-1">
|
||||||
|
<section class="container mt-5">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card card-neon">
|
||||||
|
<div class="card-body">
|
||||||
|
<h1 class="text-center mb-4">Create Your Account</h1>
|
||||||
|
<?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" id="signup-form">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="name" class="form-label">Full Name</label>
|
||||||
|
<input type="text" class="form-control" id="name" name="name" value="<?php echo htmlspecialchars($name); ?>" 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="city" class="form-label">City</label>
|
||||||
|
<input type="text" class="form-control" id="city" name="city" value="<?php echo htmlspecialchars($city); ?>" required>
|
||||||
|
</div>
|
||||||
|
<div class="d-grid">
|
||||||
|
<button type="submit" class="btn btn-primary btn-gradient">Sign Up</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="bg-dark text-white text-center p-3 mt-auto">
|
||||||
|
<p>© <?php echo date("Y"); ?> Community Hub. All Rights Reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script>
|
||||||
|
function getCity() {
|
||||||
|
if (navigator.geolocation) {
|
||||||
|
navigator.geolocation.getCurrentPosition(position => {
|
||||||
|
const lat = position.coords.latitude;
|
||||||
|
const lon = position.coords.longitude;
|
||||||
|
// Using a free reverse geocoding API
|
||||||
|
fetch(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lon}`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.address && data.address.city) {
|
||||||
|
document.getElementById('city').value = data.address.city;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => console.error("Error fetching city:", err));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.onload = getCity;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
x
Reference in New Issue
Block a user