From 3a42952593d2a017d6e643c09df504e27a61595f Mon Sep 17 00:00:00 2001
From: scoliono <2191476+scoliono@users.noreply.github.com>
Date: Mon, 27 Dec 2021 07:01:20 +0000
Subject: [PATCH] Add admin panel
---
admin/index.php | 71 +++++++++++++++++++++++++++++++++++++++++
admin/login.php | 34 ++++++++++++++++++++
admin/logout.php | 16 ++++++++++
admin/mail.php | 53 +++++++++++++++++++++++++++++++
admin/unsubscribe.php | 32 +++++++++++++++++++
css/main.css | 4 +++
index.html | 4 ++-
js/app.js | 74 +++++++++++++++++++++++++++++++++++++++++++
mail.php | 46 ---------------------------
subscribe.php | 48 ++++++++++++++--------------
10 files changed, 312 insertions(+), 70 deletions(-)
create mode 100644 admin/index.php
create mode 100644 admin/login.php
create mode 100644 admin/logout.php
create mode 100644 admin/mail.php
create mode 100644 admin/unsubscribe.php
create mode 100644 js/app.js
delete mode 100644 mail.php
diff --git a/admin/index.php b/admin/index.php
new file mode 100644
index 0000000..91d5d87
--- /dev/null
+++ b/admin/index.php
@@ -0,0 +1,71 @@
+query("SELECT * FROM subscribers");
+if (!$result) {
+ http_response_code(500);
+ die("Error: {$conn->error}");
+}
+
+$subscribers = [];
+while ($row = $result->fetch_assoc()) {
+ $subscribers[] = $row;
+}
+?>
+
+
+
+
+ Miles Linden for San Jose City Council
+
+
+ Admin Panel
+
+ Subscribers
+
+
+
+ Name |
+ Email |
+ Phone |
+
+ Join Date |
+ Actions |
+
+
+
+
+
+ = htmlspecialchars($row['full_name']) ?> |
+
+ = htmlspecialchars($row['email']) ?> |
+ = htmlspecialchars($row['phone']) ?> |
+
+ = htmlspecialchars($row['join_date']) ?> |
+
+
+ |
+
+
+
+
+
+
diff --git a/admin/login.php b/admin/login.php
new file mode 100644
index 0000000..3f3f7d9
--- /dev/null
+++ b/admin/login.php
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Signed out.
+
+
diff --git a/admin/mail.php b/admin/mail.php
new file mode 100644
index 0000000..4fdee5d
--- /dev/null
+++ b/admin/mail.php
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+query("SELECT email, full_name FROM subscribers");
+if (!$result) {
+ http_response_code(500);
+ die(json_encode(['message' => $conn->error]));
+}
+$to_emails = [];
+while ($row = $result->fetch_row()) {
+ $to_emails[] = "$row[1] <$row[0]>";
+}
+
+$to = implode(", ", $to_emails);
+$headers = [
+ 'From: Miles Linden ',
+ 'X-Mailer: PHP/' . phpversion()
+];
+$message = wordwrap($message, 80, "\r\n");
+if (!mail($to, "MILES LINDEN CAMPAIGN ALERT", $message, implode("\r\n", $headers), '-fno-reply@mileslinden.com')) {
+ http_response_code(500);
+ die("Error: failed to send email message.");
+}
+
+die("Sent email successfully.");
diff --git a/admin/unsubscribe.php b/admin/unsubscribe.php
new file mode 100644
index 0000000..0f3ce95
--- /dev/null
+++ b/admin/unsubscribe.php
@@ -0,0 +1,32 @@
+prepare("DELETE FROM subscribers WHERE email = ?");
+if (!$query) {
+ http_response_code(500);
+ die("Error: {$conn->error}");
+}
+$query->bind_param("s", $email);
+$query->execute();
+
+if ($query->affected_rows === 0) {
+ http_response_code(400);
+ die("Error: that email address does not exist");
+} else {
+ header('Location: /admin');
+ die;
+}
diff --git a/css/main.css b/css/main.css
index fb2e63a..e0dc925 100644
--- a/css/main.css
+++ b/css/main.css
@@ -98,6 +98,10 @@ nav a:hover {
min-width: 250px;
}
+.banner form input.invalid {
+ border-bottom-color: red;
+}
+
.banner input {
border: none;
font-size: 32px;
diff --git a/index.html b/index.html
index c59bad9..ff271b8 100644
--- a/index.html
+++ b/index.html
@@ -3,8 +3,10 @@
-
+
+
+
Miles Linden for San Jose City Council
diff --git a/js/app.js b/js/app.js
new file mode 100644
index 0000000..552c021
--- /dev/null
+++ b/js/app.js
@@ -0,0 +1,74 @@
+document.addEventListener('DOMContentLoaded', function () {
+
+ var fullName = document.querySelector('input[name="full_name"]');
+ var email = document.querySelector('input[name="email"]');
+ var phone = document.querySelector('input[name="phone"]');
+ var submit = document.querySelector('button[type="submit"]');
+
+ const emailRegex = /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
+ const phoneRegex = /^(\+?0?1\s?)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$/;
+ const fullNameRegex = /[^\s.]{2,} [^\s.]{2,}/;
+
+
+ fullName.addEventListener('input', function (e) {
+ if (! fullName.value.toLowerCase().match(fullNameRegex)) {
+ fullName.classList.add('invalid');
+ } else {
+ fullName.classList.remove('invalid');
+ }
+ });
+
+ email.addEventListener('input', function (e) {
+ if (! email.value.toLowerCase().match(emailRegex)) {
+ email.classList.add('invalid');
+ } else {
+ email.classList.remove('invalid');
+ }
+ });
+
+ phone.addEventListener('input', function (e) {
+ if (! phone.value.match(phoneRegex)) {
+ phone.classList.add('invalid');
+ } else {
+ phone.classList.remove('invalid');
+ }
+ });
+
+ submit.addEventListener('click', function (e) {
+ e.preventDefault();
+
+ if (! fullName.value.toLowerCase().match(fullNameRegex)) {
+ alert("Your full name appears invalid.");
+ return;
+ }
+ if (! email.value.toLowerCase().match(emailRegex)) {
+ alert("Your email address is invalid.");
+ return;
+ }
+ if (! phone.value.match(phoneRegex)) {
+ alert("Your phone number is invalid.");
+ return;
+ }
+ var fd = new FormData();
+ fd.append('full_name', fullName.value);
+ fd.append('email', email.value);
+ fd.append('phone', phone.value);
+ var req = fetch('/subscribe.php', {
+ method: 'POST',
+ body: fd
+ }).then(function (res) {
+ if (!res.ok) {
+ res.json().then(function (err) {
+ document.querySelector('input[name="'+ err.field + '"]').classList.add('invalid');
+ alert(err.message);
+ });
+ } else {
+ alert("You have subscribed successfully.");
+ fullName.value = "";
+ email.value = "";
+ phone.value = "";
+ }
+ });
+ });
+
+});
diff --git a/mail.php b/mail.php
deleted file mode 100644
index 9cebddb..0000000
--- a/mail.php
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
-
-
- Miles Linden for San Jose City Council
-
-
- Great success!
-
-
diff --git a/subscribe.php b/subscribe.php
index 61cfaf2..f8669b6 100644
--- a/subscribe.php
+++ b/subscribe.php
@@ -1,9 +1,10 @@
'email',
+ 'message' => 'Error: An email address, first name, and last name are required.'
+ ]));
}
if ($gender && $gender !== 'm' && $gender !== 'f') {
- die("Error: An invalid gender was given.");
+ http_response_code(400);
+ die(json_encode([
+ 'field' => 'full_name',
+ 'message' => 'Error: An invalid gender was given.'
+ ]));
}
-$conn = mysql_connect(":/tmp/mysql.sock", "root", "");
-if (!$conn) {
- die("MySQL connection error: " . mysql_error());
-}
-mysql_select_db("mileslinden", $conn);
+$conn = new mysqli("localhost", "mileslinden", "Daiso@6969", "mileslinden");
-$query = sprintf(
- "INSERT INTO subscribers (`email`, `full_name`, `phone`, `gender`, `join_date`) ".
- "VALUES ('%s', '%s', '%s', '%s', '%s')",
- mysql_real_escape_string($email),
- mysql_real_escape_string($fname),
- mysql_real_escape_string($phone),
- mysql_real_escape_string($gender),
+$query = $conn->prepare(
+ "INSERT INTO subscribers (`email`, `full_name`, `phone`, `gender`, `join_date`) VALUES (?, ?, ?, ?, ?)"
+);
+if (!$query) {
+ http_response_code(500);
+ die(json_encode(['message' => $conn->error]));
+}
+$query->bind_param(
+ "sssss",
+ $email, $fname, $phone_num, $gender,
date("Y-m-d H:i:s")
);
-$res = mysql_query($query);
-
-if (!$res) {
- die("MySQL query error: " . mysql_error());
-}
-
-mysql_close($conn);
+$query->execute();
?>
@@ -52,6 +54,6 @@ mysql_close($conn);
Miles Linden for San Jose City Council
- You have subscribed successfully!
+ You have subscribed successfully.