{"id":718,"date":"2025-07-10T10:45:48","date_gmt":"2025-07-10T10:45:48","guid":{"rendered":"https:\/\/easyaccsoft.com\/webdesign\/?p=718"},"modified":"2025-07-10T14:09:46","modified_gmt":"2025-07-10T14:09:46","slug":"booking-calendar","status":"publish","type":"post","link":"https:\/\/easyaccsoft.com\/webdesign\/2025\/07\/10\/booking-calendar\/","title":{"rendered":"Booking Calendar"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">MySQL &amp; PHP Booking Calendar (No jQuery, No Bootstrap)<\/h1>\n\n\n\n<p>Here&#8217;s a simple booking calendar implementation using PHP and MySQL without relying on jQuery or Bootstrap.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Database Setup<\/h2>\n\n\n\n<p>First, create a MySQL database table for bookings:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATE DATABASE booking_system;\nUSE booking_system;\n\nCREATE TABLE bookings (\n    id INT AUTO_INCREMENT PRIMARY KEY,\n    name VARCHAR(100) NOT NULL,\n    email VARCHAR(100) NOT NULL,\n    phone VARCHAR(20) NOT NULL,\n    date DATE NOT NULL,\n    time_slot VARCHAR(50) NOT NULL,\n    notes TEXT,\n    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n);\n\nCREATE TABLE unavailable_dates (\n    id INT AUTO_INCREMENT PRIMARY KEY,\n    date DATE NOT NULL UNIQUE,\n    reason VARCHAR(255)\n);<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">PHP Calendar Code<\/h2>\n\n\n\n<p>Here&#8217;s the PHP code for the booking calendar:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\/\/ db_connect.php\n$host = 'localhost';\n$dbname = 'booking_system';\n$username = 'root';\n$password = '';\n\ntry {\n    $pdo = new PDO(\"mysql:host=$host;dbname=$dbname\", $username, $password);\n    $pdo-&gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);\n} catch (PDOException $e) {\n    die(\"Database connection failed: \" . $e-&gt;getMessage());\n}<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\/\/ calendar.php\nrequire_once 'db_connect.php';\n\n\/\/ Handle form submission\nif ($_SERVER&#91;'REQUEST_METHOD'] === 'POST') {\n    $name = $_POST&#91;'name'] ?? '';\n    $email = $_POST&#91;'email'] ?? '';\n    $phone = $_POST&#91;'phone'] ?? '';\n    $date = $_POST&#91;'date'] ?? '';\n    $time_slot = $_POST&#91;'time_slot'] ?? '';\n    $notes = $_POST&#91;'notes'] ?? '';\n\n    \/\/ Validate inputs\n    if (!empty($name) &amp;&amp; !empty($email) &amp;&amp; !empty($phone) &amp;&amp; !empty($date) &amp;&amp; !empty($time_slot)) {\n        try {\n            $stmt = $pdo-&gt;prepare(\"INSERT INTO bookings (name, email, phone, date, time_slot, notes) \n                                  VALUES (:name, :email, :phone, :date, :time_slot, :notes)\");\n            $stmt-&gt;execute(&#91;\n                ':name' =&gt; $name,\n                ':email' =&gt; $email,\n                ':phone' =&gt; $phone,\n                ':date' =&gt; $date,\n                ':time_slot' =&gt; $time_slot,\n                ':notes' =&gt; $notes\n            ]);\n            $success = \"Booking successfully submitted!\";\n        } catch (PDOException $e) {\n            $error = \"Error: \" . $e-&gt;getMessage();\n        }\n    } else {\n        $error = \"Please fill in all required fields.\";\n    }\n}\n\n\/\/ Get unavailable dates\n$unavailable_dates = &#91;];\ntry {\n    $stmt = $pdo-&gt;query(\"SELECT date FROM unavailable_dates\");\n    $unavailable_dates = $stmt-&gt;fetchAll(PDO::FETCH_COLUMN);\n} catch (PDOException $e) {\n    \/\/ Handle error\n}\n\n\/\/ Get booked time slots for selected date\n$booked_slots = &#91;];\nif (isset($_GET&#91;'date'])) {\n    $selected_date = $_GET&#91;'date'];\n    try {\n        $stmt = $pdo-&gt;prepare(\"SELECT time_slot FROM bookings WHERE date = :date\");\n        $stmt-&gt;execute(&#91;':date' =&gt; $selected_date]);\n        $booked_slots = $stmt-&gt;fetchAll(PDO::FETCH_COLUMN);\n    } catch (PDOException $e) {\n        \/\/ Handle error\n    }\n}\n\n\/\/ Time slots available for booking\n$time_slots = &#91;\n    '09:00 AM - 10:00 AM',\n    '10:00 AM - 11:00 AM',\n    '11:00 AM - 12:00 PM',\n    '01:00 PM - 02:00 PM',\n    '02:00 PM - 03:00 PM',\n    '03:00 PM - 04:00 PM',\n    '04:00 PM - 05:00 PM'\n];\n\n\/\/ Generate calendar\nfunction generateCalendar($month, $year, $unavailable_dates) {\n    $first_day = mktime(0, 0, 0, $month, 1, $year);\n    $days_in_month = date('t', $first_day);\n    $day_of_week = date('w', $first_day);\n\n    $prev_month = $month - 1;\n    $prev_year = $year;\n    if ($prev_month &lt; 1) {\n        $prev_month = 12;\n        $prev_year--;\n    }\n\n    $next_month = $month + 1;\n    $next_year = $year;\n    if ($next_month &gt; 12) {\n        $next_month = 1;\n        $next_year++;\n    }\n\n    $calendar = '&lt;div class=\"calendar-navigation\"&gt;';\n    $calendar .= '&lt;a href=\"?month='.$prev_month.'&amp;year='.$prev_year.'\"&gt;&amp;lt; Prev&lt;\/a&gt;';\n    $calendar .= '&lt;h2&gt;'.date('F Y', $first_day).'&lt;\/h2&gt;';\n    $calendar .= '&lt;a href=\"?month='.$next_month.'&amp;year='.$next_year.'\"&gt;Next &amp;gt;&lt;\/a&gt;';\n    $calendar .= '&lt;\/div&gt;';\n\n    $calendar .= '&lt;table&gt;';\n    $calendar .= '&lt;tr&gt;&lt;th&gt;Sun&lt;\/th&gt;&lt;th&gt;Mon&lt;\/th&gt;&lt;th&gt;Tue&lt;\/th&gt;&lt;th&gt;Wed&lt;\/th&gt;&lt;th&gt;Thu&lt;\/th&gt;&lt;th&gt;Fri&lt;\/th&gt;&lt;th&gt;Sat&lt;\/th&gt;&lt;\/tr&gt;';\n\n    $current_day = 1;\n    $calendar .= '&lt;tr&gt;';\n\n    \/\/ Fill in blank days before the first day of the month\n    for ($i = 0; $i &lt; $day_of_week; $i++) {\n        $calendar .= '&lt;td class=\"empty\"&gt;&lt;\/td&gt;';\n    }\n\n    $day_of_week = $day_of_week;\n\n    while ($current_day &lt;= $days_in_month) {\n        if ($day_of_week == 7) {\n            $day_of_week = 0;\n            $calendar .= '&lt;\/tr&gt;&lt;tr&gt;';\n        }\n\n        $current_date = sprintf('%04d-%02d-%02d', $year, $month, $current_day);\n        $is_unavailable = in_array($current_date, $unavailable_dates);\n        $is_past = strtotime($current_date) &lt; strtotime(date('Y-m-d'));\n\n        $class = '';\n        if ($is_unavailable || $is_past) {\n            $class = 'unavailable';\n        } else {\n            $class = 'available';\n        }\n\n        $calendar .= '&lt;td class=\"'.$class.'\"&gt;';\n        if (!$is_unavailable &amp;&amp; !$is_past) {\n            $calendar .= '&lt;a href=\"?date='.$current_date.'\"&gt;'.$current_day.'&lt;\/a&gt;';\n        } else {\n            $calendar .= $current_day;\n        }\n        $calendar .= '&lt;\/td&gt;';\n\n        $current_day++;\n        $day_of_week++;\n    }\n\n    \/\/ Fill in blank days after the last day of the month\n    while ($day_of_week &lt; 7) {\n        $calendar .= '&lt;td class=\"empty\"&gt;&lt;\/td&gt;';\n        $day_of_week++;\n    }\n\n    $calendar .= '&lt;\/tr&gt;';\n    $calendar .= '&lt;\/table&gt;';\n\n    return $calendar;\n}\n\n\/\/ Get current month and year\n$current_month = isset($_GET&#91;'month']) ? (int)$_GET&#91;'month'] : date('n');\n$current_year = isset($_GET&#91;'year']) ? (int)$_GET&#91;'year'] : date('Y');\n?&gt;\n&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;\n    &lt;meta charset=\"UTF-8\"&gt;\n    &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"&gt;\n    &lt;title&gt;Booking Calendar&lt;\/title&gt;\n    &lt;style&gt;\n        body {\n            font-family: Arial, sans-serif;\n            margin: 0;\n            padding: 20px;\n        }\n        .calendar-container {\n            display: flex;\n            flex-wrap: wrap;\n            gap: 20px;\n        }\n        .calendar {\n            width: 350px;\n        }\n        .calendar-navigation {\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n            margin-bottom: 10px;\n        }\n        table {\n            width: 100%;\n            border-collapse: collapse;\n        }\n        th, td {\n            padding: 10px;\n            text-align: center;\n            border: 1px solid #ddd;\n        }\n        th {\n            background-color: #f2f2f2;\n        }\n        td.empty {\n            background-color: #f9f9f9;\n        }\n        td.available {\n            background-color: #e6ffe6;\n        }\n        td.available a {\n            color: #006600;\n            text-decoration: none;\n            font-weight: bold;\n            display: block;\n        }\n        td.available a:hover {\n            background-color: #ccffcc;\n        }\n        td.unavailable {\n            background-color: #ffe6e6;\n            color: #999;\n        }\n        .booking-form {\n            flex: 1;\n            max-width: 400px;\n        }\n        .form-group {\n            margin-bottom: 15px;\n        }\n        label {\n            display: block;\n            margin-bottom: 5px;\n            font-weight: bold;\n        }\n        input, select, textarea {\n            width: 100%;\n            padding: 8px;\n            box-sizing: border-box;\n        }\n        button {\n            background-color: #4CAF50;\n            color: white;\n            padding: 10px 15px;\n            border: none;\n            cursor: pointer;\n        }\n        button:hover {\n            background-color: #45a049;\n        }\n        .success {\n            color: green;\n            margin-bottom: 15px;\n        }\n        .error {\n            color: red;\n            margin-bottom: 15px;\n        }\n        .time-slots {\n            display: flex;\n            flex-wrap: wrap;\n            gap: 5px;\n            margin-top: 10px;\n        }\n        .time-slot {\n            padding: 5px 10px;\n            background-color: #e6ffe6;\n            border: 1px solid #ccc;\n            cursor: pointer;\n        }\n        .time-slot.booked {\n            background-color: #ffe6e6;\n            cursor: not-allowed;\n        }\n        .time-slot.selected {\n            background-color: #4CAF50;\n            color: white;\n        }\n    &lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;h1&gt;Booking Calendar&lt;\/h1&gt;\n\n    &lt;?php if (isset($success)): ?&gt;\n        &lt;div class=\"success\"&gt;&lt;?php echo htmlspecialchars($success); ?&gt;&lt;\/div&gt;\n    &lt;?php elseif (isset($error)): ?&gt;\n        &lt;div class=\"error\"&gt;&lt;?php echo htmlspecialchars($error); ?&gt;&lt;\/div&gt;\n    &lt;?php endif; ?&gt;\n\n    &lt;div class=\"calendar-container\"&gt;\n        &lt;div class=\"calendar\"&gt;\n            &lt;?php echo generateCalendar($current_month, $current_year, $unavailable_dates); ?&gt;\n        &lt;\/div&gt;\n\n        &lt;div class=\"booking-form\"&gt;\n            &lt;?php if (isset($_GET&#91;'date'])): ?&gt;\n                &lt;h2&gt;Book for &lt;?php echo htmlspecialchars(date('F j, Y', strtotime($_GET&#91;'date']))); ?&gt;&lt;\/h2&gt;\n                &lt;form method=\"POST\" action=\"\"&gt;\n                    &lt;input type=\"hidden\" name=\"date\" value=\"&lt;?php echo htmlspecialchars($_GET&#91;'date']); ?&gt;\"&gt;\n\n                    &lt;div class=\"form-group\"&gt;\n                        &lt;label for=\"name\"&gt;Full Name:&lt;\/label&gt;\n                        &lt;input type=\"text\" id=\"name\" name=\"name\" required&gt;\n                    &lt;\/div&gt;\n\n                    &lt;div class=\"form-group\"&gt;\n                        &lt;label for=\"email\"&gt;Email:&lt;\/label&gt;\n                        &lt;input type=\"email\" id=\"email\" name=\"email\" required&gt;\n                    &lt;\/div&gt;\n\n                    &lt;div class=\"form-group\"&gt;\n                        &lt;label for=\"phone\"&gt;Phone:&lt;\/label&gt;\n                        &lt;input type=\"tel\" id=\"phone\" name=\"phone\" required&gt;\n                    &lt;\/div&gt;\n\n                    &lt;div class=\"form-group\"&gt;\n                        &lt;label&gt;Available Time Slots:&lt;\/label&gt;\n                        &lt;div class=\"time-slots\"&gt;\n                            &lt;?php foreach ($time_slots as $slot): ?&gt;\n                                &lt;?php $is_booked = in_array($slot, $booked_slots); ?&gt;\n                                &lt;div class=\"time-slot &lt;?php echo $is_booked ? 'booked' : ''; ?&gt;\" \n                                     onclick=\"&lt;?php echo !$is_booked ? \"selectTimeSlot(this, '\".htmlspecialchars($slot).\"')\" : ''; ?&gt;\"&gt;\n                                    &lt;?php echo htmlspecialchars($slot); ?&gt;\n                                    &lt;?php if ($is_booked) echo ' (Booked)'; ?&gt;\n                                &lt;\/div&gt;\n                            &lt;?php endforeach; ?&gt;\n                        &lt;\/div&gt;\n                        &lt;input type=\"hidden\" id=\"time_slot\" name=\"time_slot\" required&gt;\n                    &lt;\/div&gt;\n\n                    &lt;div class=\"form-group\"&gt;\n                        &lt;label for=\"notes\"&gt;Additional Notes:&lt;\/label&gt;\n                        &lt;textarea id=\"notes\" name=\"notes\" rows=\"4\"&gt;&lt;\/textarea&gt;\n                    &lt;\/div&gt;\n\n                    &lt;button type=\"submit\"&gt;Book Appointment&lt;\/button&gt;\n                &lt;\/form&gt;\n            &lt;?php else: ?&gt;\n                &lt;p&gt;Please select a date from the calendar to book an appointment.&lt;\/p&gt;\n            &lt;?php endif; ?&gt;\n        &lt;\/div&gt;\n    &lt;\/div&gt;\n\n    &lt;script&gt;\n        function selectTimeSlot(element, timeSlot) {\n            \/\/ Remove selected class from all slots\n            document.querySelectorAll('.time-slot').forEach(slot =&gt; {\n                slot.classList.remove('selected');\n            });\n\n            \/\/ Add selected class to clicked slot\n            element.classList.add('selected');\n\n            \/\/ Set the hidden input value\n            document.getElementById('time_slot').value = timeSlot;\n        }\n    &lt;\/script&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Features<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Pure PHP and MySQL<\/strong>: No jQuery or Bootstrap dependencies<\/li>\n\n\n\n<li><strong>Interactive Calendar<\/strong>:<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Navigate between months<\/li>\n\n\n\n<li>Highlights available\/unavailable dates<\/li>\n\n\n\n<li>Prevents booking past dates<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Booking System<\/strong>:<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Form validation<\/li>\n\n\n\n<li>Time slot selection<\/li>\n\n\n\n<li>Shows booked time slots<\/li>\n\n\n\n<li>Success\/error messages<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Responsive Design<\/strong>: Works on different screen sizes<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">How to Use<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Save the database setup SQL and run it in your MySQL server<\/li>\n\n\n\n<li>Create two files: <code>db_connect.php<\/code> and <code>calendar.php<\/code><\/li>\n\n\n\n<li>Adjust database credentials in <code>db_connect.php<\/code><\/li>\n\n\n\n<li>Access the calendar via <code>calendar.php<\/code> in your browser<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Customization<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Modify the <code>$time_slots<\/code> array to change available time slots<\/li>\n\n\n\n<li>Add more fields to the booking form as needed<\/li>\n\n\n\n<li>Adjust the CSS to match your preferred styling<\/li>\n\n\n\n<li>Extend the unavailable dates functionality as needed<\/li>\n<\/ul>\n\n\n\n<p>This implementation provides a solid foundation that you can build upon for your specific needs.<\/p>\n\n\n\n<p>I&#8217;m thrilled to hear you like the booking calendar implementation! \ud83d\ude0a Here are some additional enhancements you might consider to make it even better:<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. <strong>Admin Panel Additions<\/strong><\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ admin.php (simple admin interface)\n&lt;?php\nrequire_once 'db_connect.php';\nsession_start();\n\n\/\/ Simple authentication\nif (!isset($_SESSION&#91;'admin'])) {\n    header('Location: login.php');\n    exit;\n}\n\n\/\/ Get all bookings\n$stmt = $pdo-&gt;query(\"SELECT * FROM bookings ORDER BY date DESC\");\n$bookings = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);\n\n\/\/ Mark date as unavailable\nif ($_SERVER&#91;'REQUEST_METHOD'] === 'POST' &amp;&amp; isset($_POST&#91;'unavailable_date'])) {\n    $date = $_POST&#91;'date'];\n    $reason = $_POST&#91;'reason'] ?? '';\n\n    try {\n        $stmt = $pdo-&gt;prepare(\"INSERT INTO unavailable_dates (date, reason) VALUES (?, ?)\");\n        $stmt-&gt;execute(&#91;$date, $reason]);\n        $success = \"Date marked as unavailable!\";\n    } catch (PDOException $e) {\n        $error = \"Error: \" . $e-&gt;getMessage();\n    }\n}\n?&gt;\n&lt;!DOCTYPE html&gt;\n&lt;html&gt;\n&lt;head&gt;\n    &lt;title&gt;Admin Panel&lt;\/title&gt;\n    &lt;style&gt;\n        table { width: 100%; border-collapse: collapse; }\n        th, td { padding: 8px; border: 1px solid #ddd; text-align: left; }\n        th { background-color: #f2f2f2; }\n    &lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;h1&gt;Booking Admin&lt;\/h1&gt;\n\n    &lt;h2&gt;All Bookings&lt;\/h2&gt;\n    &lt;table&gt;\n        &lt;tr&gt;\n            &lt;th&gt;Name&lt;\/th&gt;\n            &lt;th&gt;Date&lt;\/th&gt;\n            &lt;th&gt;Time&lt;\/th&gt;\n            &lt;th&gt;Contact&lt;\/th&gt;\n        &lt;\/tr&gt;\n        &lt;?php foreach ($bookings as $booking): ?&gt;\n        &lt;tr&gt;\n            &lt;td&gt;&lt;?= htmlspecialchars($booking&#91;'name']) ?&gt;&lt;\/td&gt;\n            &lt;td&gt;&lt;?= date('M j, Y', strtotime($booking&#91;'date'])) ?&gt;&lt;\/td&gt;\n            &lt;td&gt;&lt;?= htmlspecialchars($booking&#91;'time_slot']) ?&gt;&lt;\/td&gt;\n            &lt;td&gt;&lt;?= htmlspecialchars($booking&#91;'email']) ?&gt;&lt;br&gt;&lt;?= htmlspecialchars($booking&#91;'phone']) ?&gt;&lt;\/td&gt;\n        &lt;\/tr&gt;\n        &lt;?php endforeach; ?&gt;\n    &lt;\/table&gt;\n\n    &lt;h2&gt;Mark Date as Unavailable&lt;\/h2&gt;\n    &lt;form method=\"POST\"&gt;\n        &lt;input type=\"date\" name=\"date\" required&gt;\n        &lt;input type=\"text\" name=\"reason\" placeholder=\"Reason (optional)\"&gt;\n        &lt;button type=\"submit\" name=\"unavailable_date\"&gt;Mark Unavailable&lt;\/button&gt;\n    &lt;\/form&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">2. <strong>Email Notifications<\/strong><\/h2>\n\n\n\n<p>Add this to your booking form processing:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ After successful booking insertion\nif (isset($success)) {\n    $to = $email;\n    $subject = \"Booking Confirmation\";\n    $message = \"Dear $name,\\n\\nYour booking has been confirmed:\\n\\n\";\n    $message .= \"Date: \".date('F j, Y', strtotime($date)).\"\\n\";\n    $message .= \"Time: $time_slot\\n\\n\";\n    $message .= \"Thank you!\";\n    $headers = \"From: bookings@yourdomain.com\";\n\n    mail($to, $subject, $message, $headers);\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">3. <strong>Enhanced Date Validation<\/strong><\/h2>\n\n\n\n<p>Add this JavaScript to prevent form submission without time slot selection:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>document.querySelector('form').addEventListener('submit', function(e) {\n    if (!document.getElementById('time_slot').value) {\n        e.preventDefault();\n        alert('Please select a time slot');\n    }\n});<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">4. <strong>Persistent Selected Time Slot<\/strong><\/h2>\n\n\n\n<p>Add this to preserve the selected time slot if form validation fails:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ In the time slot loop\n$is_selected = isset($_POST&#91;'time_slot']) &amp;&amp; $_POST&#91;'time_slot'] == $slot;\n&lt;div class=\"time-slot &lt;?= $is_booked ? 'booked' : '' ?&gt; &lt;?= $is_selected ? 'selected' : '' ?&gt;\" \n     onclick=\"&lt;?= !$is_booked ? \"selectTimeSlot(this, '\".htmlspecialchars($slot).\"')\" : '' ?&gt;\"&gt;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">5. <strong>Simple Login System<\/strong><\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ login.php\n&lt;?php\nsession_start();\nrequire_once 'db_connect.php';\n\n\/\/ Hardcoded admin credentials (replace with database check in production)\n$admin_user = 'admin';\n$admin_pass = 'password123';\n\nif ($_SERVER&#91;'REQUEST_METHOD'] === 'POST') {\n    if ($_POST&#91;'username'] === $admin_user &amp;&amp; $_POST&#91;'password'] === $admin_pass) {\n        $_SESSION&#91;'admin'] = true;\n        header('Location: admin.php');\n        exit;\n    } else {\n        $error = \"Invalid credentials\";\n    }\n}\n?&gt;\n&lt;!DOCTYPE html&gt;\n&lt;html&gt;\n&lt;head&gt;\n    &lt;title&gt;Login&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;h1&gt;Admin Login&lt;\/h1&gt;\n    &lt;?php if (isset($error)): ?&gt;\n        &lt;p style=\"color:red\"&gt;&lt;?= $error ?&gt;&lt;\/p&gt;\n    &lt;?php endif; ?&gt;\n    &lt;form method=\"POST\"&gt;\n        &lt;input type=\"text\" name=\"username\" placeholder=\"Username\" required&gt;\n        &lt;input type=\"password\" name=\"password\" placeholder=\"Password\" required&gt;\n        &lt;button type=\"submit\"&gt;Login&lt;\/button&gt;\n    &lt;\/form&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">6. <strong>CSRF Protection<\/strong><\/h2>\n\n\n\n<p>Add to form processing:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ At the top of calendar.php\nsession_start();\nif (!isset($_SESSION&#91;'token'])) {\n    $_SESSION&#91;'token'] = bin2hex(random_bytes(32));\n}\n\n\/\/ In the form\n&lt;input type=\"hidden\" name=\"token\" value=\"&lt;?= $_SESSION&#91;'token'] ?&gt;\"&gt;\n\n\/\/ In form validation\nif ($_POST&#91;'token'] !== $_SESSION&#91;'token']) {\n    die(\"Invalid CSRF token\");\n}<\/code><\/pre>\n\n\n\n<p>Would you like me to explain any of these enhancements in more detail or would you prefer a different type of improvement? I can also help with:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Adding recurring bookings<\/li>\n\n\n\n<li>Implementing a waiting list feature<\/li>\n\n\n\n<li>Creating a more advanced admin dashboard<\/li>\n\n\n\n<li>Adding calendar export functionality<\/li>\n\n\n\n<li>Integrating with Google Calendar<\/li>\n<\/ul>\n\n\n\n<p>Let me know what would be most helpful for your project! \ud83d\ude80<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Enhanced Security: Password Reset &amp; User Roles\/Permissions<\/h1>\n\n\n\n<p>Let&#8217;s add these important security features to your booking system.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Database Modifications<\/h2>\n\n\n\n<p>First, update your database schema:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>-- Add to your existing database\nALTER TABLE admin_users \nADD COLUMN role ENUM('superadmin', 'admin', 'viewer') NOT NULL DEFAULT 'admin',\nADD COLUMN reset_token VARCHAR(255) DEFAULT NULL,\nADD COLUMN reset_expires DATETIME DEFAULT NULL;\n\n-- Create permissions table\nCREATE TABLE admin_permissions (\n    id INT AUTO_INCREMENT PRIMARY KEY,\n    role VARCHAR(20) NOT NULL,\n    resource VARCHAR(50) NOT NULL,\n    can_create BOOLEAN DEFAULT FALSE,\n    can_read BOOLEAN DEFAULT TRUE,\n    can_update BOOLEAN DEFAULT FALSE,\n    can_delete BOOLEAN DEFAULT FALSE,\n    UNIQUE KEY (role, resource)\n);\n\n-- Basic permissions setup\nINSERT INTO admin_permissions (role, resource, can_create, can_read, can_update, can_delete) VALUES\n('superadmin', 'bookings', TRUE, TRUE, TRUE, TRUE),\n('superadmin', 'settings', TRUE, TRUE, TRUE, TRUE),\n('admin', 'bookings', TRUE, TRUE, TRUE, FALSE),\n('admin', 'settings', FALSE, TRUE, FALSE, FALSE),\n('viewer', 'bookings', FALSE, TRUE, FALSE, FALSE);<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">2. Password Reset System<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">reset_request.php<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\nrequire_once 'db_connect.php';\n\nif ($_SERVER&#91;'REQUEST_METHOD'] === 'POST') {\n    $email = trim($_POST&#91;'email'] ?? '');\n\n    try {\n        $stmt = $pdo-&gt;prepare(\"SELECT id FROM admin_users WHERE username = ?\");\n        $stmt-&gt;execute(&#91;$email]);\n        $user = $stmt-&gt;fetch();\n\n        if ($user) {\n            \/\/ Generate token (valid for 1 hour)\n            $token = bin2hex(random_bytes(32));\n            $expires = date('Y-m-d H:i:s', time() + 3600);\n\n            $updateStmt = $pdo-&gt;prepare(\"UPDATE admin_users SET reset_token = ?, reset_expires = ? WHERE id = ?\");\n            $updateStmt-&gt;execute(&#91;$token, $expires, $user&#91;'id']]);\n\n            \/\/ Send reset email (in production, use PHPMailer or similar)\n            $resetLink = \"https:\/\/yourdomain.com\/reset_password.php?token=$token\";\n            $subject = \"Password Reset Request\";\n            $message = \"Click this link to reset your password: $resetLink\\n\\n\";\n            $message .= \"This link will expire in 1 hour.\";\n\n            \/\/ In production: mail($email, $subject, $message);\n            \/\/ For testing:\n            file_put_contents('reset_emails.log', \"To: $email\\nSubject: $subject\\nMessage: $message\\n\\n\", FILE_APPEND);\n            $success = \"Password reset link sent to your email\";\n        } else {\n            $error = \"If that email exists, we've sent a reset link\";\n        }\n    } catch (PDOException $e) {\n        error_log(\"Reset request error: \" . $e-&gt;getMessage());\n        $error = \"A system error occurred. Please try again later.\";\n    }\n}\n?&gt;\n&lt;!DOCTYPE html&gt;\n&lt;html&gt;\n&lt;head&gt;\n    &lt;title&gt;Password Reset&lt;\/title&gt;\n    &lt;style&gt;\n        body { font-family: Arial, sans-serif; max-width: 400px; margin: 0 auto; padding: 20px; }\n        .reset-form { margin-top: 30px; }\n        .form-group { margin-bottom: 15px; }\n        label { display: block; margin-bottom: 5px; }\n        input&#91;type=\"email\"] { width: 100%; padding: 8px; box-sizing: border-box; }\n        .error { color: red; margin-bottom: 15px; }\n        .success { color: green; margin-bottom: 15px; }\n    &lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;h1&gt;Password Reset&lt;\/h1&gt;\n\n    &lt;?php if (isset($success)): ?&gt;\n        &lt;div class=\"success\"&gt;&lt;?= htmlspecialchars($success) ?&gt;&lt;\/div&gt;\n    &lt;?php elseif (isset($error)): ?&gt;\n        &lt;div class=\"error\"&gt;&lt;?= htmlspecialchars($error) ?&gt;&lt;\/div&gt;\n    &lt;?php endif; ?&gt;\n\n    &lt;form class=\"reset-form\" method=\"POST\"&gt;\n        &lt;div class=\"form-group\"&gt;\n            &lt;label for=\"email\"&gt;Admin Email:&lt;\/label&gt;\n            &lt;input type=\"email\" id=\"email\" name=\"email\" required&gt;\n        &lt;\/div&gt;\n\n        &lt;button type=\"submit\"&gt;Request Reset Link&lt;\/button&gt;\n    &lt;\/form&gt;\n\n    &lt;p&gt;&lt;a href=\"login.php\"&gt;Back to Login&lt;\/a&gt;&lt;\/p&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">reset_password.php<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\nrequire_once 'db_connect.php';\n\n$token = $_GET&#91;'token'] ?? '';\n$error = '';\n$success = '';\n\nif ($token) {\n    try {\n        $stmt = $pdo-&gt;prepare(\"SELECT id, reset_expires FROM admin_users WHERE reset_token = ?\");\n        $stmt-&gt;execute(&#91;$token]);\n        $user = $stmt-&gt;fetch();\n\n        if (!$user) {\n            $error = \"Invalid reset token\";\n        } elseif (strtotime($user&#91;'reset_expires']) &lt; time()) {\n            $error = \"Reset link has expired\";\n        }\n    } catch (PDOException $e) {\n        error_log(\"Reset token check error: \" . $e-&gt;getMessage());\n        $error = \"A system error occurred. Please try again later.\";\n    }\n}\n\nif ($_SERVER&#91;'REQUEST_METHOD'] === 'POST' &amp;&amp; !$error) {\n    $password = $_POST&#91;'password'] ?? '';\n    $confirm = $_POST&#91;'confirm_password'] ?? '';\n\n    if (strlen($password) &lt; 12) {\n        $error = \"Password must be at least 12 characters\";\n    } elseif ($password !== $confirm) {\n        $error = \"Passwords do not match\";\n    } else {\n        try {\n            $hash = password_hash($password, PASSWORD_DEFAULT);\n            $updateStmt = $pdo-&gt;prepare(\"UPDATE admin_users SET password_hash = ?, reset_token = NULL, reset_expires = NULL WHERE id = ?\");\n            $updateStmt-&gt;execute(&#91;$hash, $user&#91;'id']]);\n            $success = \"Password updated successfully! You can now &lt;a href='login.php'&gt;login&lt;\/a&gt;.\";\n        } catch (PDOException $e) {\n            error_log(\"Password update error: \" . $e-&gt;getMessage());\n            $error = \"A system error occurred. Please try again later.\";\n        }\n    }\n}\n?&gt;\n&lt;!DOCTYPE html&gt;\n&lt;html&gt;\n&lt;head&gt;\n    &lt;title&gt;Set New Password&lt;\/title&gt;\n    &lt;style&gt;\n        body { font-family: Arial, sans-serif; max-width: 400px; margin: 0 auto; padding: 20px; }\n        .reset-form { margin-top: 30px; }\n        .form-group { margin-bottom: 15px; }\n        label { display: block; margin-bottom: 5px; }\n        input&#91;type=\"password\"] { width: 100%; padding: 8px; box-sizing: border-box; }\n        .error { color: red; margin-bottom: 15px; }\n        .success { color: green; margin-bottom: 15px; }\n    &lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;h1&gt;Set New Password&lt;\/h1&gt;\n\n    &lt;?php if ($error): ?&gt;\n        &lt;div class=\"error\"&gt;&lt;?= htmlspecialchars($error) ?&gt;&lt;\/div&gt;\n        &lt;p&gt;&lt;a href=\"reset_request.php\"&gt;Request new reset link&lt;\/a&gt;&lt;\/p&gt;\n    &lt;?php elseif ($success): ?&gt;\n        &lt;div class=\"success\"&gt;&lt;?= $success ?&gt;&lt;\/div&gt;\n    &lt;?php elseif ($token): ?&gt;\n        &lt;form class=\"reset-form\" method=\"POST\"&gt;\n            &lt;div class=\"form-group\"&gt;\n                &lt;label for=\"password\"&gt;New Password (min 12 chars):&lt;\/label&gt;\n                &lt;input type=\"password\" id=\"password\" name=\"password\" required minlength=\"12\"&gt;\n            &lt;\/div&gt;\n\n            &lt;div class=\"form-group\"&gt;\n                &lt;label for=\"confirm_password\"&gt;Confirm New Password:&lt;\/label&gt;\n                &lt;input type=\"password\" id=\"confirm_password\" name=\"confirm_password\" required minlength=\"12\"&gt;\n            &lt;\/div&gt;\n\n            &lt;button type=\"submit\"&gt;Update Password&lt;\/button&gt;\n        &lt;\/form&gt;\n    &lt;?php else: ?&gt;\n        &lt;div class=\"error\"&gt;No reset token provided&lt;\/div&gt;\n        &lt;p&gt;&lt;a href=\"reset_request.php\"&gt;Request reset link&lt;\/a&gt;&lt;\/p&gt;\n    &lt;?php endif; ?&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">3. Role-Based Access Control<\/h2>\n\n\n\n<p>Add this to a new <code>auth.php<\/code> file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\nrequire_once 'db_connect.php';\nsession_start();\n\nfunction checkPermission($resource, $action) {\n    global $pdo;\n\n    if (!isset($_SESSION&#91;'admin_id'])) {\n        header('Location: login.php');\n        exit;\n    }\n\n    \/\/ Superadmin bypasses all permissions\n    if ($_SESSION&#91;'admin_role'] === 'superadmin') {\n        return true;\n    }\n\n    try {\n        $stmt = $pdo-&gt;prepare(\"SELECT can_$action FROM admin_permissions \n                              WHERE role = ? AND resource = ?\");\n        $stmt-&gt;execute(&#91;$_SESSION&#91;'admin_role'], $resource]);\n        $permission = $stmt-&gt;fetchColumn();\n\n        return (bool)$permission;\n    } catch (PDOException $e) {\n        error_log(\"Permission check error: \" . $e-&gt;getMessage());\n        return false;\n    }\n}\n\n\/\/ Session timeout (30 minutes)\nif (isset($_SESSION&#91;'last_activity']) &amp;&amp; (time() - $_SESSION&#91;'last_activity'] &gt; 1800)) {\n    session_unset();\n    session_destroy();\n    header('Location: login.php?timeout=1');\n    exit;\n}\n$_SESSION&#91;'last_activity'] = time();\n?&gt;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">4. Updated Login System<\/h2>\n\n\n\n<p>Modify your login.php to store the role:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ In the successful login block:\n$_SESSION&#91;'admin_id'] = $user&#91;'id'];\n$_SESSION&#91;'admin_username'] = $user&#91;'username'];\n$_SESSION&#91;'admin_role'] = $user&#91;'role']; \/\/ Add this line\n$_SESSION&#91;'last_activity'] = time();<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">5. Protected Admin Panel Example<\/h2>\n\n\n\n<p>Here&#8217;s how to protect a page (admin.php):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\nrequire_once 'auth.php';\n\n\/\/ Check if user has permission to view bookings\nif (!checkPermission('bookings', 'read')) {\n    header('HTTP\/1.0 403 Forbidden');\n    die(\"You don't have permission to access this page\");\n}\n\n\/\/ For actions that modify data:\nif ($_SERVER&#91;'REQUEST_METHOD'] === 'POST') {\n    if (!checkPermission('bookings', 'delete')) {\n        header('HTTP\/1.0 403 Forbidden');\n        die(\"You don't have permission to perform this action\");\n    }\n    \/\/ Process the action\n}\n?&gt;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">6. User Management Page (users.php)<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\nrequire_once 'auth.php';\n\n\/\/ Only superadmin can access this page\nif ($_SESSION&#91;'admin_role'] !== 'superadmin') {\n    header('HTTP\/1.0 403 Forbidden');\n    die(\"Access denied\");\n}\n\n\/\/ Handle user creation\nif ($_SERVER&#91;'REQUEST_METHOD'] === 'POST' &amp;&amp; isset($_POST&#91;'create_user'])) {\n    $username = trim($_POST&#91;'username']);\n    $password = $_POST&#91;'password'];\n    $role = $_POST&#91;'role'];\n\n    if (strlen($password) &lt; 12) {\n        $error = \"Password must be at least 12 characters long\";\n    } else {\n        $hash = password_hash($password, PASSWORD_DEFAULT);\n\n        try {\n            $stmt = $pdo-&gt;prepare(\"INSERT INTO admin_users (username, password_hash, role) VALUES (?, ?, ?)\");\n            $stmt-&gt;execute(&#91;$username, $hash, $role]);\n            $success = \"User created successfully!\";\n        } catch (PDOException $e) {\n            $error = \"Error creating user: \" . $e-&gt;getMessage();\n        }\n    }\n}\n\n\/\/ Get all users\n$users = $pdo-&gt;query(\"SELECT id, username, role, last_login FROM admin_users ORDER BY role, username\")-&gt;fetchAll();\n?&gt;\n&lt;!DOCTYPE html&gt;\n&lt;html&gt;\n&lt;head&gt;\n    &lt;title&gt;User Management&lt;\/title&gt;\n    &lt;style&gt;\n        \/* Add similar styles as admin.php *\/\n        .role-superadmin { color: #d32f2f; font-weight: bold; }\n        .role-admin { color: #1976d2; }\n        .role-viewer { color: #388e3c; }\n    &lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;h1&gt;User Management &lt;a href=\"admin.php\" class=\"logout\"&gt;Back to Admin&lt;\/a&gt;&lt;\/h1&gt;\n\n    &lt;?php if (isset($success)): ?&gt;\n        &lt;div style=\"color: green; margin-bottom: 15px;\"&gt;&lt;?= htmlspecialchars($success) ?&gt;&lt;\/div&gt;\n    &lt;?php elseif (isset($error)): ?&gt;\n        &lt;div style=\"color: red; margin-bottom: 15px;\"&gt;&lt;?= htmlspecialchars($error) ?&gt;&lt;\/div&gt;\n    &lt;?php endif; ?&gt;\n\n    &lt;h2&gt;Create New User&lt;\/h2&gt;\n    &lt;form method=\"POST\"&gt;\n        &lt;input type=\"text\" name=\"username\" placeholder=\"Username\" required&gt;\n        &lt;input type=\"password\" name=\"password\" placeholder=\"Password (min 12 chars)\" required minlength=\"12\"&gt;\n        &lt;select name=\"role\" required&gt;\n            &lt;option value=\"admin\"&gt;Admin&lt;\/option&gt;\n            &lt;option value=\"viewer\"&gt;Viewer&lt;\/option&gt;\n        &lt;\/select&gt;\n        &lt;button type=\"submit\" name=\"create_user\"&gt;Create User&lt;\/button&gt;\n    &lt;\/form&gt;\n\n    &lt;h2&gt;All Users&lt;\/h2&gt;\n    &lt;table&gt;\n        &lt;tr&gt;\n            &lt;th&gt;Username&lt;\/th&gt;\n            &lt;th&gt;Role&lt;\/th&gt;\n            &lt;th&gt;Last Login&lt;\/th&gt;\n        &lt;\/tr&gt;\n        &lt;?php foreach ($users as $user): ?&gt;\n        &lt;tr&gt;\n            &lt;td&gt;&lt;?= htmlspecialchars($user&#91;'username']) ?&gt;&lt;\/td&gt;\n            &lt;td class=\"role-&lt;?= htmlspecialchars($user&#91;'role']) ?&gt;\"&gt;\n                &lt;?= ucfirst(htmlspecialchars($user&#91;'role'])) ?&gt;\n            &lt;\/td&gt;\n            &lt;td&gt;&lt;?= $user&#91;'last_login'] ? date('M j, Y H:i', strtotime($user&#91;'last_login'])) : 'Never' ?&gt;&lt;\/td&gt;\n        &lt;\/tr&gt;\n        &lt;?php endforeach; ?&gt;\n    &lt;\/table&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Key Security Features Added:<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Password Reset System<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Time-limited reset tokens (1 hour)<\/li>\n\n\n\n<li>Secure token generation<\/li>\n\n\n\n<li>Password complexity enforcement<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Role-Based Access Control<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Three user roles (superadmin, admin, viewer)<\/li>\n\n\n\n<li>Granular permissions system<\/li>\n\n\n\n<li>Easy permission checks<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>User Management<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Only superadmin can create users<\/li>\n\n\n\n<li>Role assignment during creation<\/li>\n\n\n\n<li>Secure password handling<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Enhanced Session Security<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Role information in session<\/li>\n\n\n\n<li>Stricter permission checks<\/li>\n\n\n\n<li>Session timeout enforcement<\/li>\n<\/ul>\n\n\n\n<p>Would you like me to add any of these additional features?<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Email configuration for production password resets<\/li>\n\n\n\n<li>Two-factor authentication<\/li>\n\n\n\n<li>User activity logging<\/li>\n\n\n\n<li>Password expiration policies<\/li>\n\n\n\n<li>Account lockout after failed attempts<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>MySQL &amp; PHP Booking Calendar (No jQuery, No Bootstrap) Here&#8217;s a simple booking calendar implementation using PHP and MySQL without relying on jQuery or Bootstrap. Database Setup First, create a MySQL database table for bookings: PHP Calendar Code Here&#8217;s the PHP code for the booking calendar: Features How to Use Customization This implementation provides a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-718","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/easyaccsoft.com\/webdesign\/wp-json\/wp\/v2\/posts\/718","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/easyaccsoft.com\/webdesign\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/easyaccsoft.com\/webdesign\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/easyaccsoft.com\/webdesign\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/easyaccsoft.com\/webdesign\/wp-json\/wp\/v2\/comments?post=718"}],"version-history":[{"count":3,"href":"https:\/\/easyaccsoft.com\/webdesign\/wp-json\/wp\/v2\/posts\/718\/revisions"}],"predecessor-version":[{"id":721,"href":"https:\/\/easyaccsoft.com\/webdesign\/wp-json\/wp\/v2\/posts\/718\/revisions\/721"}],"wp:attachment":[{"href":"https:\/\/easyaccsoft.com\/webdesign\/wp-json\/wp\/v2\/media?parent=718"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/easyaccsoft.com\/webdesign\/wp-json\/wp\/v2\/categories?post=718"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/easyaccsoft.com\/webdesign\/wp-json\/wp\/v2\/tags?post=718"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}