From 3516597d742465327a6020696e8b33d422e8cb12 Mon Sep 17 00:00:00 2001 From: Rajesh D <rajeshkannan7157@gmail.com> Date: Sat, 22 Mar 2025 03:41:16 +0000 Subject: [PATCH] Domain Name Project Name Changed --- app/core/config.php | 4 +- app/core/functions.php | 76 +++++--- app/pages/admin.php | 8 +- app/pages/admin/users-controller.php | 10 +- app/pages/contact.php | 2 +- app/pages/fetch_followers.php | 12 ++ app/pages/fetch_following.php | 12 ++ app/pages/follow.php | 39 ++++ app/pages/follow_action.php | 38 ++++ app/pages/home.php | 82 +++++++-- app/pages/includes/header.php | 260 +++++++++++++++++++-------- app/pages/includes/post-card.php | 12 +- app/pages/includes/slider.php | 4 +- app/pages/login.php | 61 ++++--- app/pages/post.php | 27 ++- app/pages/{blog.php => posts.php} | 0 app/pages/profile.php | 152 ++++++++++++++-- app/pages/search.php | 4 +- app/pages/signup.php | 103 ++++++----- app/pages/unfollow.php | 19 ++ app/pages/user/post.php | 38 ++-- app/pages/user/user-controller.php | 4 +- app/pages/user/user.php | 4 +- 23 files changed, 714 insertions(+), 257 deletions(-) create mode 100644 app/pages/fetch_followers.php create mode 100644 app/pages/fetch_following.php create mode 100644 app/pages/follow.php create mode 100644 app/pages/follow_action.php rename app/pages/{blog.php => posts.php} (100%) create mode 100644 app/pages/unfollow.php diff --git a/app/core/config.php b/app/core/config.php index 80e9247..0499632 100644 --- a/app/core/config.php +++ b/app/core/config.php @@ -1,4 +1,4 @@ <?php -define('ROOT','https://blog.zeal.wtf'); -define('APP_NAME',"My Blog"); +define('ROOT','https://postit.zeal.lol'); +define('APP_NAME',"Post It"); diff --git a/app/core/functions.php b/app/core/functions.php index 4bf2c7d..db5f7de 100644 --- a/app/core/functions.php +++ b/app/core/functions.php @@ -1,24 +1,28 @@ <?php -function query(string $query,array $data=[]) // $data can be empty that's why the array was empty -{ +function query(string $query, array $data = []) { try { $string = "mysql:host=" . DBHOST . ";dbname=" . DBNAME; $con = new PDO($string, DBUSER, DBPASS); - // echo "Connected successfully"; + $con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + $stm = $con->prepare($query); + $stm->execute($data); + + // Check if the query is a SELECT query + if (stripos(trim($query), 'SELECT') === 0) { + $result = $stm->fetchAll(PDO::FETCH_ASSOC); + return (!empty($result)) ? $result : false; + } + + // For INSERT, UPDATE, DELETE, return true if rows were affected + return ($stm->rowCount() > 0); + } catch (PDOException $e) { - echo "Connection failed: " . $e->getMessage(); + echo json_encode(["error" => "Database error: " . $e->getMessage()]); + return false; } -// echo $query; -// echo $data; - $stm=$con->prepare($query); - $stm->execute($data); +} - $result=$stm->fetchAll(PDO::FETCH_ASSOC); // :: is used to provide values rather than providing in query , it prevents sql injection - if(is_array($result) && !empty($result)){ - return $result; - } - return false; -} function query_row(string $query,array $data=[]) // $data can be empty that's why the array was empty { @@ -159,25 +163,37 @@ function esc(string $string) } //phpinfo(); -function find($table, $id = null, $column = '*') -{ +function find($table, $id = null, $column = '*') { $st = ""; - + $params = []; + if (!empty($id)) { - $st = "id = '".intval($id)."' AND "; // Secure ID usage + $st = "id = :id AND "; // Using `user_id` instead of `id` for flexibility + $params['id'] = intval($id); } - $query = "SELECT $column FROM $table WHERE {$st}active = 1 LIMIT 1"; - $result = query($query); + $query = "SELECT $column FROM $table WHERE {$st}active = 1"; - if ($result) { - return $result[0][$column] ?? ''; // Safe array access + // If counting posts, modify the query accordingly + if ($column === 'COUNT(id) AS count') { + $st = "user_id = :id AND "; // Using `user_id` instead of `id` for flexibility + $params['id'] = intval($id); + $query = "SELECT COUNT(id) AS count FROM $table WHERE {$st}active = 1"; + } else { + $query .= " LIMIT 1"; } - - return ''; + + $result = query($query, $params); + + if ($column === 'COUNT(id) AS count') { + return $result[0]['count'] ?? 0; // Return the count value + } + + return $result ? $result[0][$column] ?? '' : ''; } + function resize_image($filename, $max_size = 1000) { if (!file_exists($filename)) { @@ -273,4 +289,16 @@ function timepicker($date){ $date = "less than a minute ago"; } return $date; +} +function getFollowCounts($user_id){ + $queryFollowers = "SELECT COUNT(*) AS followers FROM followers WHERE following_id = :id"; + $queryFollowing = "SELECT COUNT(*) AS following FROM followers WHERE follower_id = :id"; + + $followers = query($queryFollowers, ['id' => $user_id]); + $following = query($queryFollowing, ['id' => $user_id]); + + return [ + 'followers' => $followers[0]['followers'] ?? 0, + 'following' => $following[0]['following'] ?? 0 + ]; } \ No newline at end of file diff --git a/app/pages/admin.php b/app/pages/admin.php index 31ba4c9..fba4a01 100644 --- a/app/pages/admin.php +++ b/app/pages/admin.php @@ -319,7 +319,7 @@ if($role == 'user'){ </svg> <header class="navbar sticky-top bg-dark flex-md-nowrap p-0 shadow" data-bs-theme="dark"> - <a class="navbar-brand col-md-3 col-lg-2 me-0 px-3 fs-6 text-white" href="<?=ROOT?>/home">Photogram</a> + <a class="navbar-brand col-md-3 col-lg-2 me-0 px-3 fs-6 text-white" href="<?=ROOT?>/home">Post-It</a> <ul class="navbar-nav flex-row d-md-none"> <li class="nav-item text-nowrap"> @@ -432,13 +432,13 @@ if($role == 'user'){ } ?> <div class="btn-toolbar mb-2 mb-md-0"> - <? if($section =='users'){ + <? if($section =='users' and $action== 'view'){ echo '<a href="users/add" class="btn btn-primary">Add User</a>' ; } - elseif($section =='categories'){ + elseif($section =='categories' and $action== 'view'){ echo '<a href="categories/add" class="btn btn-primary">Add Category</a>' ; } - elseif ($section == 'posts') { + elseif ($section == 'posts' and $action== 'view') { echo '<a href="posts/add" class="btn btn-primary">Add Post</a>' ; } ?> diff --git a/app/pages/admin/users-controller.php b/app/pages/admin/users-controller.php index fea0d03..a58c584 100644 --- a/app/pages/admin/users-controller.php +++ b/app/pages/admin/users-controller.php @@ -15,9 +15,9 @@ if($action == 'add'){ { $errors['username']="Username already exists"; } - elseif(preg_match('/[^a-zA-Z0-9]/',$_POST['username'])) + elseif(preg_match('/[^a-zA-Z0-9._]/', $_POST['username'])) { - $errors['username']="Username can only contain alphabets and numbers"; + $errors['username'] = "Username can only contain alphabets, numbers, underscores, and dots"; } elseif(strlen($_POST['username'])<5) { @@ -135,9 +135,9 @@ elseif($action=='edit'){ { $errors['username']="Username already exists"; } - elseif(preg_match('/[^a-zA-Z0-9]/',$_POST['username'])) + elseif(preg_match('/[^a-zA-Z0-9._]/', $_POST['username'])) { - $errors['username']="Username can only contain alphabets and numbers"; + $errors['username'] = "Username can only contain alphabets, numbers, underscores, and dots"; } elseif(strlen($_POST['username'])<5) { @@ -238,7 +238,7 @@ elseif($action=='edit'){ $data['image']=$savePath; if(empty($_POST['password'])) { - $query="UPDATE users SET username=:username,email=:email,image=:image,role=:role WHERE id=:id"; + $query="UPDATE users SET username=:username,email=:email,image=:image,role=:role,bio=:bio WHERE id=:id"; } else { diff --git a/app/pages/contact.php b/app/pages/contact.php index bb7ebed..73b58c1 100644 --- a/app/pages/contact.php +++ b/app/pages/contact.php @@ -68,7 +68,7 @@ </div> <form class="row mb-3" action="//api.web3forms.com/submit" method="POST" name="contactform"> <input type="hidden" name="access_key" value="53cbd4c6-8fda-4b19-aceb-975b5fdea86c"> - <input type="hidden" name="redirect" value="https://blog.zeal.wtf/"> + <input type="hidden" name="redirect" value="https://postit.zeal.lol/"> <input type="hidden" name="from_name" value="<?=ROOT?>"> <div class="col-md-6 p-3"> <input required placeholder="First Name" type="text" name="name" class="form-control" /> diff --git a/app/pages/fetch_followers.php b/app/pages/fetch_followers.php new file mode 100644 index 0000000..881ea20 --- /dev/null +++ b/app/pages/fetch_followers.php @@ -0,0 +1,12 @@ +<?php + +$user_id = $_GET['user_id'] ?? $_SESSION['user_id']; + +$query = "SELECT users.id, users.username, users.image + FROM followers + JOIN users ON followers.follower_id = users.id + WHERE followers.following_id = :user_id"; +$followers = query($query, ['user_id' => $user_id]); + +echo json_encode($followers); +?> diff --git a/app/pages/fetch_following.php b/app/pages/fetch_following.php new file mode 100644 index 0000000..5810c43 --- /dev/null +++ b/app/pages/fetch_following.php @@ -0,0 +1,12 @@ +<?php + +$user_id = $_GET['user_id'] ?? $_SESSION['user_id']; + +$query = "SELECT users.id, users.username, users.image + FROM followers + JOIN users ON followers.following_id = users.id + WHERE followers.follower_id = :user_id"; +$following = query($query, ['user_id' => $user_id]); + +echo json_encode($following); +?> diff --git a/app/pages/follow.php b/app/pages/follow.php new file mode 100644 index 0000000..2414e3a --- /dev/null +++ b/app/pages/follow.php @@ -0,0 +1,39 @@ +<?php +error_reporting(E_ALL); +ini_set('display_errors', 1); +if (!isset($_SESSION['user_id'])) { + echo json_encode(["error" => "Not logged in"]); + exit(); +} + +$follower_id = $_SESSION['user_id']; +$following_id = $_POST['following_id']; + +// Check if the user is already following +echo $checkQuery = "SELECT COUNT(*) as count FROM followers WHERE follower_id = $follower_id AND following_id = $following_id"; +$exists = query_row($checkQuery); + +if ($exists['count'] > 0) { + echo json_encode(["error" => "Already following this user"]); + exit; +} + +if ($follower_id == $following_id) { + echo json_encode(["error" => "You can't follow yourself"]); + exit(); +} + +try { + $query = "INSERT INTO followers (follower_id, following_id) VALUES (:follower_id, :following_id)"; + $result = query($query, ['follower_id' => $follower_id, 'following_id' => $following_id]); + var_dump($result); + if ($result) { + echo json_encode(["success" => "Followed successfully"]); + } else { + echo json_encode(["error" => "Already following or error occurred"]); + } +} catch (PDOException $e) { + echo json_encode(["error" => "Database error: " . $e->getMessage()]); +} + +?> diff --git a/app/pages/follow_action.php b/app/pages/follow_action.php new file mode 100644 index 0000000..1339aac --- /dev/null +++ b/app/pages/follow_action.php @@ -0,0 +1,38 @@ +<?php + +if (!isset($_SESSION['user_id'])) { + echo json_encode(["error" => "Not logged in"]); + exit(); +} + +$follower_id = $_SESSION['user_id']; +$following_id = $_POST['following_id']; + +// Check if already following +$checkQuery = "SELECT COUNT(*) as fcount FROM followers WHERE follower_id = :follower_id AND following_id = :following_id"; +$alreadyFollowing = query_row($checkQuery, ['follower_id' => $follower_id, 'following_id' => $following_id]); + +if ($alreadyFollowing['fcount'] > 0) { + // Unfollow (Delete from database) + $deleteQuery = "DELETE FROM followers WHERE follower_id = :follower_id AND following_id = :following_id"; + query($deleteQuery, ['follower_id' => $follower_id, 'following_id' => $following_id]); + $status = "Follow"; +} else { + // Follow (Insert into database) + $insertQuery = "INSERT INTO followers (follower_id, following_id) VALUES (:follower_id, :following_id)"; + query($insertQuery, ['follower_id' => $follower_id, 'following_id' => $following_id]); + $status = "Following"; +} + +// Get updated follower count +$queryFollowers = "SELECT COUNT(*) AS followers FROM followers WHERE following_id = :id"; +$followers = query($queryFollowers, ['id' => $following_id]); +$followerCount = $followers[0]['followers'] ?? 0; + + +echo json_encode([ + "success" => ($status === "Following" ? "Followed" : "Unfollowed"), + "status" => $status, + "followers" => $followerCount +]); +?> diff --git a/app/pages/home.php b/app/pages/home.php index 8d56276..36d101c 100644 --- a/app/pages/home.php +++ b/app/pages/home.php @@ -1,25 +1,77 @@ <? include 'includes/header.php';?> <!--blog--> - -<main class="container mt-5"> -<h2>Your Feed</h2> <?php -$query = "SELECT posts.*, categories.category, users.username , users.image as image_user,users.id as userid - FROM posts JOIN categories ON posts.category_id = categories.id - JOIN users ON posts.user_id = users.id - WHERE posts.active = 1 ORDER BY posts.id DESC;"; -$result = query($query); +$user_id = $_SESSION['user_id'] ?? null; +$feed_type = $_GET['feed'] ?? ''; +?> +<main class="container mt-5"> +<h2>Your Feed</h2><?php if(logged_in()){?> + <div class="dropdown mb-3"> + <button class="btn btn-primary dropdown-toggle" type="button" id="feedDropdown" data-bs-toggle="dropdown" aria-expanded="false"> + <?= $feed_type === 'following' ? 'Following' : 'All Posts' ?> + </button> + <ul class="dropdown-menu" aria-labelledby="feedDropdown"> + <li><a class="dropdown-item" href="<?= ROOT ?>">All Posts</a></li> + + <li><a class="dropdown-item" href="<?= ROOT ?>/?feed=following">Following</a></li> + + </ul> + </div><?php } ?> + <?php + // If user selects "following" feed, show posts only from followed users + if ($feed_type === 'following' && $user_id) { + $feed = " AND users.id IN (SELECT following_id FROM followers WHERE follower_id = :user_id)"; + } + else{ + $feed = ''; + } + $query = "SELECT posts.*, categories.category, users.username , users.image as image_user,users.id as userid + FROM posts JOIN categories ON posts.category_id = categories.id + JOIN users ON posts.user_id = users.id + WHERE posts.active = 1 $feed ORDER BY posts.id DESC;"; + $params = ($feed_type === 'following' && $user_id) ? ['user_id' => $user_id] : []; + $result = query($query, $params); -if($result){ - include 'includes/post-card.php'; -} - else{ - echo '<div class="alert alert-danger">Post not found</div>'; - echo '<a href="'.ROOT.'/admin/posts" class="btn btn-primary">Back to posts</a>'; + if($result){ + include 'includes/post-card.php'; } - ?> + else{ + echo '<div class="alert alert-danger">Post not found</div>'; + echo '<a href="'.ROOT.'" class="btn btn-primary">Back to posts</a>'; + } + ?> </main> +<?php + $showModal = false; // Default + // Example check: If username or profile picture is missing + if(logged_in()){ + $ima = find('users',$_SESSION['user_id'],'image'); + if (empty($ima)) { + $showModal = true; + } + } + + ?> + + <script> + document.addEventListener("DOMContentLoaded", function() { + <?php if ($showModal): ?> + var profileModal = new bootstrap.Modal(document.getElementById('profileSetupModal')); + profileModal.show(); + + // Handle "Do It Later" button click + document.getElementById('skipProfile').addEventListener('click', function() { + profileModal.hide(); + localStorage.setItem('profileSkipped', 'true'); // Store in localStorage to prevent showing again + }); + // Prevent modal from showing again if skipped + if (localStorage.getItem('profileSkipped') === 'true') { + profileModal.hide(); + } + <?php endif; ?> + }); + </script> <? include 'includes/footer.php';?> diff --git a/app/pages/includes/header.php b/app/pages/includes/header.php index ce9db0f..9bf22b7 100644 --- a/app/pages/includes/header.php +++ b/app/pages/includes/header.php @@ -1,3 +1,4 @@ + <html lang="en" data-bs-theme="auto"> <script src="<?=ROOT?>/assets/js/color-modes.js"></script> @@ -139,7 +140,15 @@ .like-btn .bi-heart-fill { color: red; /* Filled heart color */ } + .nav-link.active { + color:#0d6efd !important; /* Change active color */ + font-weight: bold; /* Make it stand out */ + } + :hover{ + color:#0d6efd !important; /* Change hover color */ + transition: color 0.3s ease-in-out; + } </style> @@ -148,7 +157,76 @@ <link href="<?=ROOT?>/assests/css/headers.css" rel="stylesheet"> <script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.13/cropper.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.13/cropper.min.css"> - +<script> + document.addEventListener("DOMContentLoaded", function () { + document.querySelectorAll(".share-btn").forEach(button => { + button.addEventListener("click", function () { + let postUrl = this.getAttribute("data-url"); + let shareText = "Check out this awesome post!"; + + // Social Media Share Buttons with Icons + let shareOptions = ` + <div class="d-flex flex-column align-items-center"> + <a href="https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(postUrl)}" target="_blank" class="btn btn-primary btn-sm w-100 my-1 d-flex align-items-center"> + <i class="bi bi-facebook fs-5 me-2"></i> Share on Facebook + </a> + <a href="https://twitter.com/intent/tweet?url=${encodeURIComponent(postUrl)}&text=${encodeURIComponent(shareText)}" target="_blank" class="btn btn-info btn-sm w-100 my-1 d-flex align-items-center"> + <i class="bi bi-twitter fs-5 me-2"></i> Share on Twitter + </a> + <a href="https://api.whatsapp.com/send?text=${encodeURIComponent(postUrl)}" target="_blank" class="btn btn-success btn-sm w-100 my-1 d-flex align-items-center"> + <i class="bi bi-whatsapp fs-5 me-2"></i> Share on WhatsApp + </a> + <button class="btn btn-secondary btn-sm w-100 my-1 d-flex align-items-center copy-link-btn" data-url="${postUrl}"> + <i class="bi bi-link-45deg fs-5 me-2"></i> Copy Link + </button> + </div> + `; + + // Remove any existing modal before creating a new one + let existingModal = document.getElementById("shareModal"); + if (existingModal) { + existingModal.remove(); + } + + // Create the modal with fade-in animation + let shareModal = document.createElement("div"); + shareModal.innerHTML = ` + <div class="modal fade show" id="shareModal" tabindex="-1" style="display: block; background: rgba(0,0,0,0.5);"> + <div class="modal-dialog modal-dialog-centered animate__animated animate__zoomIn"> + <div class="modal-content border-0 shadow-lg rounded"> + <div class="modal-header bg-primary text-white"> + <h5 class="modal-title"><i class="bi bi-share-fill me-2"></i> Share Post</h5> + <button type="button" class="btn-close text-white" id="closeModal"></button> + </div> + <div class="modal-body text-center"> + ${shareOptions} + </div> + </div> + </div> + </div> + `; + document.body.appendChild(shareModal); + + // Add fade-out animation when closing + document.getElementById("closeModal").addEventListener("click", function () { + let modal = document.getElementById("shareModal"); + modal.classList.remove("animate__zoomIn"); + modal.classList.add("animate__zoomOut"); + setTimeout(() => modal.remove(), 500); + }); + + // Copy link functionality + document.querySelector(".copy-link-btn").addEventListener("click", function () { + navigator.clipboard.writeText(this.getAttribute("data-url")).then(() => { + let copyBtn = this; + copyBtn.innerHTML = '<i class="bi bi-check-circle-fill text-success me-2"></i> Link Copied!'; + setTimeout(() => copyBtn.innerHTML = '<i class="bi bi-link-45deg fs-5 me-2"></i> Copy Link', 2000); + }); + }); + }); + }); +}); +</script> </head> <body> <svg xmlns="http://www.w3.org/2000/svg" class="d-none"> @@ -197,110 +275,136 @@ </ul> </div> - + + <!-- Profile Setup Modal --> +<div id="profileSetupModal" class="modal fade" tabindex="-1" aria-hidden="true"> + <div class="modal-dialog modal-dialog-centered"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title">Set Up Your Image </h5> + <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> + </div> + <div class="modal-body text-center"> + <p>Complete your profile now or do it later.</p> + <a href="<?=ROOT?>/user/user/edit" class="btn btn-primary">Set Up Profile</a> + <button class="btn btn-secondary" id="skipProfile">Do It Later</button> + </div> + </div> + </div> +</div> <?php $current_page = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), "/"); ?> -<header class="p-3 border-bottom"> +<nav class="navbar navbar-expand-lg bg-body-tertiary shadow-sm rounded"> <div class="container"> - <div class="d-flex flex-wrap align-items-center justify-content-center"> - <!-- Logo --> - <a href="/" class="d-flex justify-content-left align-items-center mb-2 mb-lg-0 mx-md-5 link-body-emphasis text-decoration-none"> - <img src="<?=ROOT?>/assets/images/blogger.png" alt="Logo" class="img-fluid" style="width: 50px; max-height: 50px; object-fit: contain;"> - </a> - - <!-- Navigation Bar --> - <ul class="nav nav-pills justify-content-center gap-3 py-2 rounded shadow-sm" id="navBar"> + <!-- Logo --> + <a class="navbar-brand fw-bold text-primary" href="<?=ROOT?>"> + <img src="<?=ROOT?>/assets/images/blogger.png" alt="Logo" class="rounded-circle shadow-sm me-2" + style="width: 45px; height: 45px; object-fit: cover;"> + Post-It + </a> + + <!-- Navbar Toggle --> + <button class="navbar-toggler border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"> + <span class="navbar-toggler-icon"></span> + </button> + + <!-- Navbar Content --> + <div class="collapse navbar-collapse" id="navbarNav"> + <ul class="navbar-nav me-auto mb-2 mb-lg-0"> <li class="nav-item"> - <a class="nav-link d-flex align-items-center gap-2 fw-semibold px-3 py-2 <?= ($current_page == '' || $current_page == 'index.php') ? 'active' : '' ?>" - href="<?=ROOT?>"> - <i class="bi bi-house-door-fill"></i> Home + <a class="nav-link fw-semibold <?= ($current_page == '' || $current_page == 'index.php') ? 'active' : '' ?>" href="<?=ROOT?>"> + <i class="bi bi-house-door"></i> Home </a> </li> <li class="nav-item"> - <a class="nav-link d-flex align-items-center gap-2 fw-semibold px-3 py-2 <?= $current_page == 'blog' ? 'active' : '' ?>" - href="<?=ROOT?>/blog"> - <i class="bi bi-images"></i> Blog + <a class="nav-link fw-semibold <?= $current_page == 'posts' ? 'active' : '' ?>" href="<?=ROOT?>/posts"> + <i class="bi bi-file-earmark-text"></i> Post </a> </li> <li class="nav-item"> - <a class="nav-link d-flex align-items-center gap-2 fw-semibold px-3 py-2 <?= $current_page == 'contact' ? 'active' : '' ?>" - href="<?=ROOT?>/contact"> - <i class="bi bi-chat-text-fill"></i> Contact + <a class="nav-link fw-semibold <?= $current_page == 'contact' ? 'active' : '' ?>" href="<?=ROOT?>/contact"> + <i class="bi bi-envelope"></i> Contact </a> </li> - <?php if (!in_array($url[0], ['admin', 'blog', 'search', 'profile', 'post', 'contact', 'user'])): ?> + <!-- Category Dropdown --> <li class="nav-item dropdown"> - <a href="#" class="nav-link d-flex align-items-center justify-content-center dropdown-toggle <?= $current_page == 'category' ? 'active' : '' ?>" - data-bs-toggle="dropdown" aria-expanded="false"> - <i class="bi bi-tags-fill"></i> Category + <a href="#" class="nav-link dropdown-toggle fw-semibold" data-bs-toggle="dropdown"> + <i class="bi bi-tags"></i> Categories </a> - <?php - $query = "SELECT * FROM categories WHERE active=1"; - $categories = query($query); - ?> - <ul class="dropdown-menu text-small"> - <?php foreach ($categories as $category): ?> + <ul class="dropdown-menu border-0 shadow-sm"> + <?php + $query = "SELECT * FROM categories WHERE active=1"; + $categories = query($query); + foreach ($categories as $category): ?> <li><a class="dropdown-item" href="<?=ROOT?>/category/<?=$category['slug']?>"><?=$category['category']?></a></li> - <?php endforeach; ?> + <?php endforeach; ?> </ul> </li> - <?php endif; ?> </ul> + </div> - <!-- Search Bar & User Profile --> - <div class="d-flex align-items-center"> - <!-- Search Form --> - <form action="<?=ROOT?>/search" class="d-flex align-items-center me-3 mt-3" role="search"> - <div class="input-group" style="max-width: 250px;"> - <input value="<?=$_GET['find'] ?? ''?>" name="find" - type="search" - class="form-control rounded-start-pill px-4 shadow-sm" - placeholder="Search..." - aria-label="Search"> - <button type="submit" class="btn btn-primary rounded-end-pill"> - <i class="bi bi-search"></i> - </button> - </div> - </form> - - <!-- User Profile Dropdown --> - <?php if(logged_in()){ - $image_user = find('users', $_SESSION['user_id'], 'image'); - $role = find('users', $_SESSION['user_id'], 'role'); - - } ?> - <div class="dropdown text-end"> - <a href="#" class="d-flex align-items-center link-body-emphasis text-decoration-none dropdown-toggle" - data-bs-toggle="dropdown" aria-expanded="false"> - <img src="<?=get_image($image_user)?>" alt="User Image" class="img-fluid rounded-circle" - style="width: 50px; height: 50px; object-fit: cover;"> + <!-- Keep Search Bar and Profile Always Visible --> + <div class="d-flex align-items-center"> + <!-- Search Bar --> + <form class="d-flex me-3 mt-3" action="<?=ROOT?>/search" role="search"> + <input class="form-control me-2 rounded-pill" value="<?=$_GET['find'] ?? ''?>" name="find" type="search" placeholder="Search" aria-label="Search"> + <button class="btn btn-outline-primary rounded-pill" type="submit"> + <i class="bi bi-search"></i> + </button> + </form> + + <!-- User Profile --> + <?php if(logged_in()){ + $image_user = find('users', $_SESSION['user_id'], 'image'); + $role = find('users', $_SESSION['user_id'], 'role'); + } ?> + + <div class="dropdown"> + <a href="#" class="d-flex align-items-center text-decoration-none dropdown-toggle" data-bs-toggle="dropdown"> + <img src="<?=get_image($image_user)?>" alt="User Image" class="rounded-circle border shadow-sm" + style="width: 40px; height: 40px; object-fit: cover;"> + </a> + <ul class="dropdown-menu dropdown-menu-end shadow-sm"> + <a class="dropdown-item" href="https://postit.zeal.lol/user/user/edit"> + + <li class="dropdown-header text-center fw-bold"><img src="<?=get_image($image_user)?>" alt="User Image" class="rounded-circle border shadow-sm" + style="width: 40px; height: 40px; object-fit: cover;"> User Menu</li> </a> - <ul class="dropdown-menu text-small"> - <li> - <a class="dropdown-item" href="<?= ($role == 'admin') ? '/admin/posts/add' : '/user/post/add'; ?>"> - New Post... - </a> - </li> - <li><a class="dropdown-item" href="<?=ROOT?>/admin">Admin</a></li> - <li><a class="dropdown-item" href="<?=ROOT?>/profile/<?=$_SESSION['user_id']?>">Profile</a></li> - <li><hr class="dropdown-divider"></li> - <?php if(!logged_in()): ?> - <li><a class="dropdown-item" href="<?=ROOT?>/login">Sign in</a></li> - <?php else: ?> - <li><a class="dropdown-item" href="<?=ROOT?>/logout">Sign out</a></li> - <?php endif; ?> - </ul> - </div> - </div> <!-- End of Search & Profile --> + <li><hr class="dropdown-divider"></li> + <li><a class="dropdown-item" href="<?= ($role == 'admin') ? '/admin/posts/add' : '/user/post/add'; ?>"> + <i class="bi bi-plus-circle"></i> New Post + </a></li> + <li><a class="dropdown-item" href="<?=ROOT?>/profile/<?=$_SESSION['user_id']?>"> + <i class="bi bi-person"></i> Profile + </a></li> + <li><a class="dropdown-item" href="<?=ROOT?>/admin"> + <i class="bi bi-gear"></i> Admin + </a></li> + <li><hr class="dropdown-divider"></li> + <?php if(!logged_in()): ?> + <li><a class="dropdown-item" href="<?=ROOT?>/login"> + <i class="bi bi-box-arrow-right"></i> Login + </a></li> + <?php else : ?> + <li><a class="dropdown-item" href="<?=ROOT?>/logout"> + <i class="bi bi-box-arrow-right"></i> Logout + </a></li> + <?php endif; ?> + </ul> + </div> </div> </div> -</header> +</nav> + + + + - <? +<? if($url[0]=='home') include 'slider.php'?> diff --git a/app/pages/includes/post-card.php b/app/pages/includes/post-card.php index 953f628..2d191ad 100644 --- a/app/pages/includes/post-card.php +++ b/app/pages/includes/post-card.php @@ -72,10 +72,19 @@ <!-- Comments --> <div class="d-flex align-items-center"> - <i class="bi bi-chat fs-5 me-1 text-secondary"></i> + <i class="bi bi-chat fs-5 me-1 text-primary"></i> <a href="<?=ROOT?>/post/<?=$post['slug']?>" class="text-muted text-decoration-none"><?= $num_comment['num'] ?> Comments</a> </div> + <!-- Share Button --> + <div class="d-flex align-items-center"> + <i class="bi bi-share fs-5 me-1 text-primary"></i> + <a href="javascript:void(0);" class="share-btn text-muted text-decoration-none mx-1" data-url="<?= ROOT ?>/post/<?= $post['slug'] ?>"> + Share + </a> + + </div> </div> + <!-- Date at Bottom Right --> <div class="d-flex justify-content-end mt-3"> @@ -123,5 +132,6 @@ document.addEventListener("DOMContentLoaded", function() { }); }); }); + </script> diff --git a/app/pages/includes/slider.php b/app/pages/includes/slider.php index 4e8b622..f076463 100644 --- a/app/pages/includes/slider.php +++ b/app/pages/includes/slider.php @@ -69,8 +69,8 @@ <div class="carousel-inner"> <?php $query = "SELECT image AS all_images FROM users - WHERE active = 1 UNION ALL SELECT image - FROM posts WHERE active = 1 ORDER BY RAND() LIMIT 5"; + WHERE active = 1 and image != null UNION ALL SELECT image + FROM posts WHERE active = 1 ORDER BY RAND() LIMIT 5"; $post = query($query); ?> <?php if (!empty($post)): ?> diff --git a/app/pages/login.php b/app/pages/login.php index c3303ac..7be86f7 100644 --- a/app/pages/login.php +++ b/app/pages/login.php @@ -160,38 +160,37 @@ else{ </div> -<main class="form-signin w-100 m-auto"> - <form method="POST"> - <a href="<?=ROOT?>/home"> - <img class="mb-4 rounded-circle shadow" src="<?=ROOT?>/assets/images/logo.png" alt="" width="72" height="57" style="object-fit:cover;"> +<main class="form-signin w-100 mx-auto"> +<div class="d-flex justify-content-center align-items-center vh-100"> + <div class="p-3 rounded shadow-lg text-center bg-white" style="width: 100%; max-width: 400px;"> + <a href="<?=ROOT?>/home" class="d-flex justify-content-center"> + <img class="mb-3 rounded-circle shadow" src="<?=ROOT?>/assets/images/logo.png" alt="" width="80" height="80" style="object-fit: cover;"> </a> - <h1 class="h3 mb-3 fw-normal">Please sign in</h1> - <?php - if(!empty($errors)){ - echo '<div class="alert alert-danger">'; - foreach($errors as $error){ - echo $error.'<br>'; - } - echo '</div>'; - } - ?> - <div class="form-floating"> - <input value="<?oldvalue('email')?>" type="text" name="email" class="form-control" id="floatingInput" placeholder="name@example.com"> - <label for="floatingInput">Username or Email address</label> - </div> - <div class="form-floating"> - <input value="<?oldvalue('password')?>" type="password" name="password" class="form-control" id="floatingPassword" placeholder="Password"> - <label for="floatingPassword">Password</label> - </div> - <div class="my-2">Don't have an account? <a href="<?=ROOT?>/signup">Signup here</a></div> - <div class="form-check text-start my-3"> - <input class="form-check-input" name=remember type="checkbox" value="1" id="flexCheckDefault"> - <label class="form-check-label" for="flexCheckDefault"> - Remember me - </label> - </div> - <button class="btn btn-primary w-100 py-2" type="submit">Sign in</button> - </form> + <h1 class="h4 mb-3 fw-bold">Please Sign In</h1> + + <?php if (!empty($errors)) : ?> + <div class="alert alert-danger"> + <?php foreach ($errors as $error) echo $error . '<br>'; ?> + </div> + <?php endif; ?> + + <form method="POST"> + <div class="form-floating mb-3"> + <input value="<?= oldvalue('email') ?>" type="text" name="email" class="form-control" id="floatingInput" placeholder="name@example.com"> + <label for="floatingInput">Username or Email Address</label> + </div> + <div class="form-floating mb-3"> + <input value="<?= oldvalue('password') ?>" type="password" name="password" class="form-control" id="floatingPassword" placeholder="Password"> + <label for="floatingPassword">Password</label> + </div> + <div class="my-2"> + Don't have an account? <a href="<?=ROOT?>/signup" class="text-primary">Signup here</a> + </div> + <button class="btn btn-primary w-100 py-2" type="submit">Sign In</button> + </form> + </div> +</div> + </main> <script src="<?=ROOT?>/assets/js/bootstrap/bootstrap.bundle.min.js"></script> diff --git a/app/pages/post.php b/app/pages/post.php index cd870bc..977aa31 100644 --- a/app/pages/post.php +++ b/app/pages/post.php @@ -78,6 +78,16 @@ if($result){ <img src="<?= get_image($image) ?>" class="bd-placeholder-img bd-placeholder-img-lg featurette-image img-fluid mx-auto border rounded" style="width: 100%; height: auto; object-fit: cover;"> + <!-- Save Button --> + <div class="text-center"> + <a href="<?= get_image($image) ?>" style="color: black !important;" download="post-image.jpg" class="btn btn-outline-primary mt-3 px-4 py-2 text-dark shadow-sm"> + <i class="bi bi-download"></i> Save + </a> + <a href="javascript:void(0);" style="color: black !important;" class="share-btn btn btn-outline-primary mt-3 px-4 py-2 text-dark shadow-sm" data-url="<?= ROOT ?>/post/<?= $post['slug'] ?>"> + <i class="bi bi-share"></i> Share + </a> + </div> + </div> <!-- Post Content --> @@ -249,7 +259,7 @@ if($result){ <!-- Edit & Delete Buttons --> <?php if($userid == $_SESSION['user_id']): ?> <div class="text-left mt-3"> - <a href="<?=ROOT?>/user/post/edit/<?=$id?>" class="btn btn-outline-primary px-3 py-2 shadow-sm"> + <a href="<?=ROOT?>/user/post/edit/<?=$id?>" style="color:blue !important;" class="btn btn-outline-primary px-3 py-2 shadow-sm"> <i class="bi bi-pencil"></i> Edit Post </a> <a data-bs-toggle="modal" data-bs-target="#deleteModal" class="btn btn-outline-danger px-3 py-2 shadow-sm"> @@ -316,5 +326,20 @@ else{ }); }); +document.addEventListener("DOMContentLoaded", function () { + document.querySelectorAll(".save-btn").forEach(button => { + button.addEventListener("click", function () { + let imgURL = this.getAttribute("data-image"); + let link = document.createElement("a"); + link.href = imgURL; + link.download = "post-image.jpg"; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + alert("Image saved successfully!"); + }); + }); +}); + </script> <!--blog--> diff --git a/app/pages/blog.php b/app/pages/posts.php similarity index 100% rename from app/pages/blog.php rename to app/pages/posts.php diff --git a/app/pages/profile.php b/app/pages/profile.php index f51aedf..406cc27 100644 --- a/app/pages/profile.php +++ b/app/pages/profile.php @@ -349,17 +349,27 @@ include 'includes/header.php'; <!--- Php Files --> <?php if (!empty($url[1])) { - $id = $url[1]; + $profile_id = $url[1]; } else { - $id = $_SESSION['user_id']; + $profile_id = $_SESSION['user_id']; } -$image_user = find('users', $id, 'image'); -$username = find('users' ,$id ,'username'); -$bio = find('users',$id,'bio'); -$query = "select count(id) as count from posts where user_id = $id and active = 1"; -$post_no = query($query); -$postn = $post_no[0]['count']; +$image_user = find('users', $profile_id, 'image'); +$username = find('users' ,$profile_id ,'username'); +$bio = find('users',$profile_id,'bio'); + +$postn = find('posts', $profile_id, 'COUNT(id) AS count'); + +// Count followers +$queryFollowers = "SELECT COUNT(*) AS followers FROM followers WHERE following_id = :id"; +$followers = query($queryFollowers, ['id' => $profile_id]); +$followerCount = $followers[0]['followers'] ?? 0; + + +$profile_user_id = $profile_id; // The user whose profile is being viewed + +$counts = getFollowCounts($profile_id); + ?> <header> <div class="container"> @@ -373,16 +383,26 @@ $postn = $post_no[0]['count']; </div> - <div class="profile-user-settings"> + <div class="profile-user-settings align-items-center justify-content-center"> <h1 class="profile-user-name"><?=$username?></h1> <?php if($url[1] == $_SESSION['user_id']){?> - <a href="<?=ROOT?>/user/user/edit" class="btn profile-edit-btn">Edit Profile</a> - <? } ?> + <a href="<?=ROOT?>/user/user/edit" class=" mx-3 btn profile-edit-btn">Edit Profile</a> + <? } + + else{ + $checkQuery = "SELECT COUNT(*) as fcount FROM followers WHERE follower_id = :follower_id AND following_id = :following_id"; + $isFollowing = query_row($checkQuery, ['follower_id' => $_SESSION['user_id'], 'following_id' => $profile_user_id]); + ?> + <button id="follow-btn" class="mx-3 btn profile-edit-btn" + onclick="toggleFollow(<?= $profile_user_id ?>)"> + <?= ($isFollowing['fcount'] > 0) ? 'Following' : 'Follow' ?> + </button> + <?php } ?> </div> <div class="profile-stats"> - <ul> + <ul class="align-items-center"> <li class="nav-item"> <a class="nav-link d-flex align-items-center gap-2" href=""> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-images" viewBox="0 0 16 16"> @@ -392,13 +412,40 @@ $postn = $post_no[0]['count']; <?=$postn?> Posts </a> </li> - <li><span class="profile-stat-count">188</span> followers</li> - <li><span class="profile-stat-count">206</span> following</li> + <li class="nav-item"><a href="#" class="nav-link" data-bs-toggle="modal" data-bs-target="#followersModal"> <span class="profile-stat-count" id="follower-count"><?= $counts['followers'] ?></span> followers</a></li> + <li class="nav-item"><a href="#" class="nav-link" data-bs-toggle="modal" data-bs-target="#followingModal"> <span class="profile-stat-count" id="following-count"><?= $counts['following'] ?></span> following</a></li> </ul> + <div class="modal fade" id="followersModal" tabindex="-1" aria-labelledby="followersModalLabel" aria-hidden="true"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="followersModalLabel">Followers</h5> + <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> + </div> + <div class="modal-body"> + <ul id="followers-list" class="list-group"></ul> + </div> + </div> + </div> + </div> + + <div class="modal fade" id="followingModal" tabindex="-1" aria-labelledby="followingModalLabel" aria-hidden="true"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="followingModalLabel">Following</h5> + <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> + </div> + <div class="modal-body"> + <ul id="following-list" class="list-group"></ul> + </div> + </div> + </div> + </div> </div> - <div class="profile-bio justify-content-center"> + <div class="profile-bio align-items-center justify-content-center"> <p><span class="profile-real-name"><?=$bio?></span></p> @@ -419,8 +466,8 @@ $postn = $post_no[0]['count']; <div class="container"> <div class="row"> <?php - $query = "SELECT * FROM posts WHERE user_id = $id AND active = 1 ORDER BY id DESC"; - $posts = query($query); + $query = "SELECT * FROM posts WHERE user_id = :id AND active = 1 ORDER BY id DESC"; + $posts = query($query, ['id' => $profile_id]); ?> <?php if (!empty($posts)): ?> <?php foreach ($posts as $post): ?> @@ -435,7 +482,7 @@ $postn = $post_no[0]['count']; $query = "SELECT COUNT(*) as num FROM likes WHERE post_id = $post[id]"; $likes = query_row($query); $likes = $likes['num']; - $query = "Select count(id) as num from comments where post_id = $id and active = 1"; + $query = "Select count(id) as num from comments where post_id = $post[id] and active = 1"; $num_comment = query_row($query); ?> <div class="card-body text-center"> @@ -464,3 +511,72 @@ $postn = $post_no[0]['count']; <!-- End of container --> </main> +<script> +// followers following popup + document.addEventListener("DOMContentLoaded", function () { + document.querySelector('[data-bs-target="#followersModal"]').addEventListener("click", function () { + fetchFollowers(); + }); + + document.querySelector('[data-bs-target="#followingModal"]').addEventListener("click", function () { + fetchFollowing(); + }); + }); + + function fetchFollowers() { + fetch("<?=ROOT?>/fetch_followers?user_id=<?= $profile_id ?>") + .then(response => response.json()) + .then(data => { + let list = document.getElementById("followers-list"); + list.innerHTML = ""; // Clear existing list + if (data.length > 0) { + data.forEach(user => { + list.innerHTML += `<li class="list-group-item"> <a href="<?=ROOT?>/profile/${user.id}" class="text-decoration-none text-dark"><img src="${user.image}" width="30" class="rounded-circle"> ${user.username}</a></li>`; + }); + } else { + list.innerHTML = "<li class='list-group-item'>No followers</li>"; + } + }); + } + + function fetchFollowing() { + fetch("<?=ROOT?>/fetch_following?user_id=<?= $profile_id ?>") + .then(response => response.json()) + .then(data => { + let list = document.getElementById("following-list"); + list.innerHTML = ""; // Clear existing list + if (data.length > 0) { + data.forEach(user => { + list.innerHTML += `<li class="list-group-item"><a href="<?=ROOT?>/profile/${user.id}" class="text-decoration-none text-dark"><img src="${user.image}" width="30" class="rounded-circle"> ${user.username}</a></li>`; + }); + } else { + list.innerHTML = "<li class='list-group-item'>Not following anyone</li>"; + } + }); + } +/// + + function toggleFollow(profileUserId) { + let followBtn = document.getElementById("follow-btn"); + let followerCount = document.getElementById("follower-count"); + + fetch("<?=ROOT?>/follow_action", { + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded" + }, + body: `following_id=${profileUserId}` + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + followBtn.innerText = data.status; + followerCount.innerText = data.followers; // Update follower count + } else if (data.error) { + alert(data.error); + } + }) + .catch(error => console.error("Error:", error)); + } + +</script> \ No newline at end of file diff --git a/app/pages/search.php b/app/pages/search.php index a303aea..03b50e7 100644 --- a/app/pages/search.php +++ b/app/pages/search.php @@ -12,7 +12,7 @@ $query = "SELECT posts.*, categories.category, users.username, users.image AS image_user FROM posts JOIN categories ON posts.category_id = categories.id JOIN users ON posts.user_id = users.id WHERE posts.active = 1 - AND (posts.title LIKE :find OR categories.category LIKE :find OR posts.content LIKE :find) + AND (users.username LIKE :find OR posts.title LIKE :find OR categories.category LIKE :find OR posts.content LIKE :find) ORDER BY posts.id DESC"; $result = query($query,['find'=>$find]); @@ -26,7 +26,7 @@ if($result){ } else{ echo '<div class="alert alert-danger">Search not found</div>'; - echo '<a href="'.ROOT.'/blog" class="btn btn-primary">Back to Blogs</a>'; + echo '<a href="'.ROOT.'" class="btn btn-primary">Back to Home</a>'; } } ?> diff --git a/app/pages/signup.php b/app/pages/signup.php index f3c654b..26e7f9f 100644 --- a/app/pages/signup.php +++ b/app/pages/signup.php @@ -12,9 +12,9 @@ if(isset($_POST['email']) || isset($_POST['password']) || isset($_POST['username { $errors['username']="Username already exists"; } - elseif(preg_match('/[^a-zA-Z0-9]/',$_POST['username'])) + elseif(preg_match('/[^a-zA-Z0-9._]/', $_POST['username'])) { - $errors['username']="Username can only contain alphabets and numbers"; + $errors['username'] = "Username can only contain alphabets, numbers, underscores, and dots"; } elseif(strlen($_POST['username'])<5) { @@ -209,58 +209,65 @@ if(isset($_POST['email']) || isset($_POST['password']) || isset($_POST['username </div> -<main class="form-signin w-100 m-auto"> - <form method="POST" action="<?=ROOT?>/signup"> - <a href="<?=ROOT?>/home"> - <img class="mb-4 rounded-circle shadow" src="<?=ROOT?>/assets/images/logo.png" alt="" width="72" height="57" style="object-fit:cover;"> + <div class="m-auto d-flex justify-content-center align-items-center"> + <div class="p-5 rounded shadow-lg bg-white text-center" style="width: 100%; max-width: 500px;"> + + <a href="<?=ROOT?>/home" class="d-flex justify-content-center"> + <img class="mb-3 rounded-circle shadow" src="<?=ROOT?>/assets/images/logo.png" alt="" width="90" height="90" style="object-fit: cover;"> </a> - <h1 class="h3 mb-3 fw-normal">Create User</h1> - <?php - if(!empty($errors)) - { - echo '<div class="alert alert-danger">'; - echo '<ul>'; - foreach($errors as $error) - { - echo '<li>'.$error.'</li>'; - } - echo '</ul>'; - echo '</div>'; - } - ?> + + <h1 class="h4 mb-4 fw-bold">Create Your Account</h1> + + <?php if (!empty($errors)) : ?> + <div class="alert alert-danger"> + <ul> + <?php foreach ($errors as $error) echo "<li>$error</li>"; ?> + </ul> + </div> + <?php endif; ?> + <div class="alert alert-danger d-none" id="alert"> - <ul id="error-list"> - </ul> - </div> - <div class="form-floating"> - <input value="<?oldvalue('username')?>" type="text" name=username class="form-control" id="floatingInput" placeholder="name@example.com" required> - <label for="floatingInput">Username</label> + <ul id="error-list"></ul> </div> - <div class="form-floating"> - <input value="<?oldvalue('email')?>" type="email" name=email class="form-control" id="floatingInput" placeholder="name@example.com"> - <label for="floatingInput">Email address</label> - </div> + <form method="POST" action="<?=ROOT?>/signup"> + <div class="form-floating mb-3"> + <input value="<?= oldvalue('username') ?>" type="text" name="username" class="form-control" id="floatingUsername" placeholder="Username" required> + <label for="floatingUsername">Username</label> + </div> + + <div class="form-floating mb-3"> + <input value="<?= oldvalue('email') ?>" type="email" name="email" class="form-control" id="floatingEmail" placeholder="name@example.com" required> + <label for="floatingEmail">Email Address</label> + </div> + + <div class="form-floating mb-3"> + <input value="<?= oldvalue('password') ?>" type="password" name="password" class="form-control" id="floatingPassword" placeholder="Password" required> + <label for="floatingPassword">Password</label> + </div> + + <div class="form-floating mb-3"> + <input value="<?= oldvalue('retype_password') ?>" type="password" name="retype_password" class="form-control" id="floatingRetypePassword" placeholder="Retype Password" required> + <label for="floatingRetypePassword">Retype Password</label> + </div> + + <div class="my-3"> + Already have an account? <a href="<?=ROOT?>/login" class="text-primary fw-semibold">Login here</a> + </div> + + <div class="form-check text-start mb-4"> + <input <?= old_checked('tc') ?> name="tc" class="form-check-input" type="checkbox" value="1" id="flexCheckDefault" required> + <label class="form-check-label" for="flexCheckDefault"> + I accept the <a href="#" class="text-primary fw-semibold">Terms & Conditions</a> + </label> + </div> + + <button class="btn btn-primary w-100 py-3" type="submit">Sign Up</button> + </form> + </div> +</div> - <div class="form-floating"> - <input value="<?oldvalue('password')?>" type="password" name=password class="form-control" id="floatingPassword" placeholder="Password"> - <label for="floatingPassword">Password</label> - </div> - <div class="form-floating"> - <input value="<?oldvalue('retype_password')?>" type="password" name=retype_password class="form-control" id="floatingPassword" placeholder="name@example.com"> - <label for="floatingInput">Retype Password</label> - </div> - <div class="my-2">Already have an account? <a href="<?=ROOT?>/login">Login here</a></div> - <div class="form-check text-start my-3"> - <input <?old_checked('tc')?> name="tc" class="form-check-input" type="checkbox" value="1" id="flexCheckDefault"> - <label class="form-check-label" for="flexCheckDefault"> - Accept Terms & Conditions - </label> - </div> - <button class="btn btn-primary w-100 py-2" type="submit">Sign Up</button> - </form> -</main> <script src="<?=ROOT?>/assets/js/bootstrap/bootstrap.bundle.min.js"></script> diff --git a/app/pages/unfollow.php b/app/pages/unfollow.php new file mode 100644 index 0000000..a7001b7 --- /dev/null +++ b/app/pages/unfollow.php @@ -0,0 +1,19 @@ +<?php +if (!isset($_SESSION['user_id'])) { + echo json_encode(["error" => "Not logged in"]); + exit(); +} + +$follower_id = $_SESSION['user_id']; +$following_id = $_POST['following_id']; + +$query = "DELETE FROM followers WHERE follower_id = :follower_id AND following_id = :following_id"; +$result = query($query, ['follower_id' => $follower_id, 'following_id' => $following_id]); + +if ($result) { + echo json_encode(["success" => "Unfollowed successfully"]); +} else { + echo json_encode(["error" => "Error unfollowing user"]); +} + +?> diff --git a/app/pages/user/post.php b/app/pages/user/post.php index eff928d..dc4c1d0 100644 --- a/app/pages/user/post.php +++ b/app/pages/user/post.php @@ -1,25 +1,21 @@ <?php if($action == 'add'):?> <!-- Add posts form or functionality here --> - <div class="container d-flex justify-content-center mt-5 mb-5"> - <div class="w-50 p-4 shadow-lg rounded-4 bg-white border border-1"> - <form method="POST" action="<?=ROOT?>/user/post/add" enctype="multipart/form-data"> - <h2 class="text-center mb-4 fw-bold text-primary">Create Your Post</h2> - - <!-- Error Messages --> - <?php if (!empty($errors)): ?> - <div class="alert alert-danger"> - <ul> - <?php foreach ($errors as $error): ?> - <li><?= $error ?></li> - <?php endforeach; ?> - </ul> - </div> - <?php endif; ?> + <div class="container d-flex justify-content-center mt-5"> + <div class="card shadow-lg p-4" style="width: 100%; max-width: 600px; border-radius: 10px;"> + <h1 class="h3 mb-3 fw-bold text-center">Create Post</h1> - <div class="alert alert-danger d-none" id="alert"> - <ul id="error-list"></ul> + <?php if (!empty($errors)): ?> + <div class="alert alert-danger"> + <ul> + <?php foreach ($errors as $error): ?> + <li><?= $error ?></li> + <?php endforeach; ?> + </ul> </div> + <?php endif; ?> + <form method="POST" action="<?=ROOT?>/user/post/add" enctype="multipart/form-data"> + <!-- Image Upload --> <div class="text-center"> @@ -40,7 +36,7 @@ <!-- Title Input --> - <div class="form-floating"> + <div class="form-floating mt-5"> <input value="<?oldvalue('title')?>" type="text" name="title" class="form-control rounded-3" id="floatingInput" placeholder="Title" required> <label for="floatingInput">Title</label> </div> @@ -123,7 +119,7 @@ <input type="hidden" name="cropped_image" id="croppedImageData"> <!-- Title --> - <div class="form-floating mb-3 mt-3"> + <div class="form-floating mb-3 mt-5"> <input value="<?=oldvalue('title',$posts['title'])?>" type="text" name="title" class="form-control" id="floatingInput" placeholder="Title" required> @@ -154,12 +150,12 @@ </select> <label for="dropdown1">Category</label> </div> - <!-- Buttons --> <div class="d-flex justify-content-between mt-4"> - <a href="<?=ROOT?>/admin/posts" class="btn btn-outline-secondary px-4 py-2">Back</a> + <a href="<?=ROOT?>/post/<?=$posts['slug']?>" class="btn btn-outline-secondary px-4 py-2">Back</a> <button class="btn btn-primary px-4 py-2 shadow-sm" type="submit">Save</button> </div> + </form> </div> </div> diff --git a/app/pages/user/user-controller.php b/app/pages/user/user-controller.php index 9f5441d..39f6af8 100644 --- a/app/pages/user/user-controller.php +++ b/app/pages/user/user-controller.php @@ -14,9 +14,9 @@ if($action=='edit'){ { $errors['username']="Username already exists"; } - elseif(preg_match('/[^a-zA-Z0-9]/',$_POST['username'])) + elseif(preg_match('/[^a-zA-Z0-9._]/', $_POST['username'])) { - $errors['username']="Username can only contain alphabets and numbers"; + $errors['username'] = "Username can only contain alphabets, numbers, underscores, and dots"; } elseif(strlen($_POST['username'])<5) { diff --git a/app/pages/user/user.php b/app/pages/user/user.php index 95c0571..2bcdfaf 100644 --- a/app/pages/user/user.php +++ b/app/pages/user/user.php @@ -79,7 +79,7 @@ <!-- Buttons --> <div class="d-flex justify-content-between"> - <a href="<?=ROOT?>" class="btn btn-outline-secondary px-4">Back</a> + <a href="<?=ROOT?>/profile/<?=$user['id']?>" class="btn btn-outline-secondary px-4">Back</a> <button class="btn btn-primary px-4" type="submit">Save</button> </div> </form> @@ -89,7 +89,7 @@ <?php } else{ echo '<div class="alert alert-danger">User not found</div>'; - echo '<a href="'.ROOT.'/admin/users" class="btn btn-primary">Back to Users</a>'; + echo '<a href="'.ROOT.'" class="btn btn-primary">Back to Home</a>'; } ?> <?php endif; ?> -- GitLab