Begin conversion to day camp registration system

master
Skylar Ittner 5 years ago
parent 5c90ae4b76
commit 326cb874e7

Binary file not shown.

@ -1,114 +0,0 @@
<?php
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
class Child {
private $id;
private $familyid;
private $name;
private $birthday;
private $graduated;
public function __construct() {
}
public function load(int $id): Child {
global $database;
$info = $database->get('people', ["familyid", "name", "birthday", "graduated"], ['personid' => $id]);
$this->id = $id;
$this->familyid = $info['familyid'];
$this->name = $info['name'];
$this->birthday = strtotime($info['birthday']);
$this->graduated = $info['graduated'] == 1;
return $this;
}
public function save() {
global $database;
if (is_int($this->id) && $database->has("people", ['personid' => $this->id])) {
$database->update("people", ["name" => $this->name, "birthday" => date("Y-m-d", $this->birthday), "graduated" => $this->graduated], ['personid' => $this->id]);
} else {
$database->insert("people", ["familyid" => $this->familyid, "name" => $this->name, "birthday" => date("Y-m-d", $this->birthday), "graduated" => $this->graduated]);
$this->id = $database->id();
}
}
public static function exists(int $cid, int $fid = null) {
global $database;
if (is_null($fid)) {
return $database->has("people", [
'personid' => $cid
]);
}
return $database->has("people", ["AND" => [
'familyid' => $fid,
'personid' => $cid
]]);
}
public function getID(): int {
return $this->id;
}
public function getFamilyID(): int {
return $this->familyid;
}
public function getFamily(): Family {
return (new Family())->load($this->familyid);
}
public function getName(): string {
return $this->name;
}
/**
* Get the person's birth date as a UNIX timestamp.
* @return int
*/
public function getBirthday(): int {
return $this->birthday;
}
public function isGraduated(): bool {
return $this->graduated == true;
}
public function setName(string $name) {
$this->name = $name;
}
/**
* Set the person's birth date to either a UNIX timestamp or a date string.
* @param int $timestamp
* @param string $date A string parseable by strtotime().
*/
public function setBirthday(int $timestamp = null, string $date = null) {
if (is_null($timestamp) && !is_null($date)) {
$this->birthday = strtotime($date);
} else if (!is_null($timestamp) && is_null($date)) {
$this->birthday = $timestamp;
}
}
public function setGraduated(bool $graduated) {
$this->graduated = $graduated;
}
public function setFamilyID(int $id) {
$this->familyid = $id;
}
public function setFamily(Family $f) {
$this->familyid = $f->getID();
}
}

@ -1,291 +0,0 @@
<?php
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
class Family {
private $id;
private $name = "";
private $father = "";
private $mother = "";
private $phone = "";
private $email = "";
private $address = "";
private $city = "";
private $state = "";
private $zip = "";
private $photo = false;
private $newsletter = 1;
private $children = [];
private $expires = 0;
private $private = false;
public function __construct() {
}
/**
* Load a family from the database into this object
* @global type $database
* @param int $familyid
* @return \Family
* @throws Exception
*/
public function load(int $familyid): Family {
global $database;
if ($database->has("families", ['familyid' => $familyid])) {
$this->id = $familyid;
} else {
throw new Exception("No such family exists.");
}
$f = $database->get("families", [
'familyid (id)',
'familyname (name)',
'phone',
'email',
'newsletter_method (newsletter)',
'address',
'city',
'state',
'zip',
'father_name (father)',
'mother_name (mother)',
'photo_permission (photo)',
'expires',
'private'
], [
"familyid" => $this->id
]);
$children = $database->select("people", 'personid', ["familyid" => $this->id]);
$this->name = $f['name'];
$this->father = $f['father'];
$this->mother = $f['mother'];
$this->phone = $f['phone'];
$this->email = $f['email'];
$this->address = $f['address'];
$this->city = $f['city'];
$this->state = $f['state'];
$this->zip = $f['zip'];
$this->photo = $f['photo'] == 1;
$this->newsletter = $f['newsletter'];
$this->expires = strtotime($f['expires']);
$this->private = $f['private'] == 1;
foreach ($children as $c) {
$this->children[] = (new Child())->load($c);
}
return $this;
}
public function save() {
global $database;
if (is_int($this->id) && $database->has("families", ['familyid' => $this->id])) {
$database->update("families", [
"familyname" => $this->getName(),
"father_name" => $this->getFather(),
"mother_name" => $this->getMother(),
"phone" => $this->getPhone(),
"email" => $this->getEmail(),
"address" => $this->getAddress(),
"city" => $this->getCity(),
"state" => $this->getState(),
"zip" => $this->getZip(),
"photo_permission" => $this->getPhotoPermission(),
"newsletter_method" => $this->getNewsletter(),
"expires" => date("Y-m-d", $this->getExpires()),
"private" => $this->getPrivate()
], [
"familyid" => $this->id
]);
} else {
$database->insert("families", [
"familyname" => $this->getName(),
"father_name" => $this->getFather(),
"mother_name" => $this->getMother(),
"phone" => $this->getPhone(),
"email" => $this->getEmail(),
"address" => $this->getAddress(),
"city" => $this->getCity(),
"state" => $this->getState(),
"zip" => $this->getZip(),
"photo_permission" => $this->getPhotoPermission(),
"newsletter_method" => $this->getNewsletter(),
"expires" => date("Y-m-d", $this->getExpires()),
"private" => $this->getPrivate()
]);
$this->id = $database->id();
}
for ($i = 0; $i < count($this->children); $i++) {
$this->children[$i]->setFamilyID($this->id);
$this->children[$i]->save();
}
}
public function getID() {
return $this->id;
}
public function getName(): string {
return $this->name;
}
public function getFather(): string {
return $this->father;
}
public function getMother(): string {
return $this->mother;
}
public function getPhone(): string {
return $this->phone;
}
public function getEmail(): string {
return $this->email;
}
public function getAddress(): string {
return $this->address;
}
public function getCity(): string {
return $this->city;
}
public function getState(): string {
return $this->state;
}
public function getZip(): string {
return $this->zip;
}
public function getPhotoPermission(): bool {
return $this->photo == true;
}
public function getNewsletter(): int {
return $this->newsletter;
}
public function getChildren(): array {
return $this->children;
}
public function getExpires(): int {
return $this->expires;
}
public function getPrivate(): bool {
return $this->private == true;
}
public function setName(string $name) {
$this->name = $name;
}
public function setFather(string $name) {
$this->father = $name;
}
public function setMother(string $name) {
$this->mother = $name;
}
public function setPhone(string $phone) {
$phone = preg_replace("/[^0-9]/", "", $phone);
if (strlen($phone) == 11) {
$phone = preg_replace("/^1/", "", $phone);
}
if (strlen($phone) != 10) {
throw new Exception("Enter a valid 10-digit phone number.");
}
$this->phone = $phone;
}
public function setEmail(string $email) {
$email = strtolower($email);
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new Exception("The email address looks wrong.");
}
$this->email = $email;
}
public function setAddress(string $address) {
$this->address = $address;
}
public function setCity(string $city) {
$this->city = $city;
}
/**
* Set the state, in two-character form.
* @param string $state
* @throws Exception
*/
public function setState(string $state) {
$state = strtoupper($state);
if (!preg_match("/^[A-Z]{2}$/", $state)) {
throw new Exception("Select a valid state.");
}
$this->state = strtoupper($state);
}
public function setZip(string $zip) {
if (!preg_match("/^[0-9]{5}(-?[0-9]{4})?$/", $zip)) {
throw new Exception("Enter a valid five or nine digit US ZIP code.");
}
$this->zip = $zip;
}
public function setPhotoPermission(bool $perm) {
$this->photo = $perm;
}
public function setNewsletter(int $newsletter) {
if (!is_int($newsletter) || !($newsletter == 1 || $newsletter == 2 || $newsletter == 3)) {
throw new Exception("Invalid newsletter preference.");
}
$this->newsletter = $newsletter;
}
public function setChildren(array $children) {
$this->children = $children;
}
public function addChild(Child $child) {
$this->children[] = $child;
}
/**
* Set the membership expiration date to either a UNIX timestamp or a date
* string.
* @param int $timestamp
* @param string $date A string parseable by strtotime().
*/
public function setExpires(int $timestamp = null, string $date = null) {
if (is_null($timestamp) && !is_null($date)) {
$this->expires = strtotime($date);
} else if (!is_null($timestamp) && is_null($date)) {
$this->expires = $timestamp;
}
}
public function setPrivate(bool $private) {
$this->private = $private;
}
}

@ -3,7 +3,7 @@
<type>org.netbeans.modules.php.project</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/php-project/1">
<name>MembershipPortal</name>
<name>CampPortal</name>
</data>
</configuration>
</project>

@ -8,24 +8,18 @@
require_once __DIR__ . "/../../lib/requiredpublic.php";
require_once __DIR__ . "/../../lib/Family.lib.php";
require_once __DIR__ . "/../../lib/Child.lib.php";
require_once __DIR__ . "/../../lib/Email.lib.php";
var_export($_POST);
die();
function errorBack(string $errormsg) {
header("Location: ../?page=signup&error=" . htmlentities($errormsg));
die($errormsg);
}
if (empty($_POST['agree_terms'])) {
errorBack("You must agree to HACHE's policy.");
}
$family = new Family();
$renewal = false;
if (!empty($_SESSION['familyid']) && $database->has("families", ['familyid' => $_SESSION['familyid']])) {
$family = (new Family())->load($_SESSION['familyid']);
$family = $_SESSION['familyid'];
$renewal = true;
} else if (!empty($_POST['renewing'])) {
// Session expired, but we're renewing, so kick them back to verification

@ -7,15 +7,9 @@
require_once __DIR__ . "/../lib/requiredpublic.php";
$page = "entry.php";
$page = "signup.php";
if (!empty($_GET['page'])) {
switch ($_GET['page']) {
case "renew":
$page = "renew.php";
break;
case "verify":
$page = "verify.php";
break;
case "signup":
$page = "signup.php";
break;
@ -32,9 +26,12 @@ if (!empty($_GET['page'])) {
<title><?php echo $SETTINGS["site_title"]; ?></title>
<link rel="icon" href="static/logo.svg">
<link href="static/bootstrap.min.css" rel="stylesheet">
<link href="static/material-color.min.css" rel="stylesheet">
<link href="static/style.css" rel="stylesheet">
<script src="static/jquery-3.3.1.min.js"></script>
<script src="static/fontawesome-all.min.js"></script>
<script src="static/bootstrap.bundle.min.js"></script>
<script src="static/solid.min.js"></script>
<script src="static/fontawesome.min.js"></script>
<?php
include_once __DIR__ . "/parts/$page";

@ -1,81 +0,0 @@
<?php
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
if (empty($IN_SITE)) {
die("Access denied.");
}
?>
<div class="container mt-4">
<div class="row justify-content-center">
<div class="card mb-4 col-lg-8">
<div class="card-body">
<div class="text-center">
<img class="img-fluid mb-4" style="max-height: 100px; min-width: 100px;" src="static/hachelogo.svg" alt="HACHE: Helena Area Christian Home Educators"/>
<h1>Renew Your Membership</h1>
<div class="card-text">
<p>
Please enter your email address below. You'll be
sent a verification code. This is to ensure nobody
else can view or change your family's information.
</div>
<?php
$msg = "";
$alert = "danger";
if (!empty($_GET['msg'])) {
switch ($_GET['msg']) {
case "sessionexpired":
$msg = "You took too long and were automatically logged out. Please try again.";
break;
case "noemail":
$msg = "We don't have that email on file for any current families.";
break;
case "bademail":
$msg = "That email address doesn't look right. Please try again.";
break;
case "tooearly":
$alert = "info";
if (!empty($_GET['exp']) && is_numeric($_GET['exp']) && $_GET['exp'] * 1 > time()) {
$msg = "<i class=\"fas fa-calendar-check\"></i> This membership isn't expiring until " . date("F j, Y", $_GET['exp'] * 1) . " and cannot be renewed yet.";
} else {
// Somebody is screwing with the URL
// for some reason
$msg = "<i class=\"fas fa-calendar-check\"></i> This membership isn't close enough to expiration and cannot be renewed yet.";
}
break;
}
}
if ($msg != "") {
?>
<div class="alert alert-<?php echo $alert; ?>">
<?php echo $msg; ?>
</div>
<?php
}
?>
<form action="./?page=verify" method="POST">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">
<i class="fas fa-at fa-fw"></i>
</span>
</div>
<input type="email" class="form-control" name="email" placeholder="family@example.com" autofocus />
<div class="input-group-append">
<button type="submit" class="btn btn-primary">Continue <i class="fas fa-chevron-right"></i></button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>

@ -9,58 +9,33 @@ if (empty($IN_SITE)) {
die("Access denied.");
}
$familyname = "";
$fathername = "";
$mothername = "";
$streetaddress = "";
$city = "";
$state = "";
$zip = "";
$phone = "";
$email = "";
$newsletter_method = "";
$children = [];
$campers = [];
$adults = [];
$youth = [];
if (isset($_SESSION['familyid']) && $database->has('families', ['familyid' => $_SESSION['familyid']])) {
$familyinfo = $database->get("families", ['familyname', 'phone', 'email', 'address', 'city', 'state', 'zip', 'father_name (fathername)', 'mother_name (mothername)', 'newsletter_method'], ['familyid' => $_SESSION['familyid']]);
$children = $database->select("people", 'personid', ['familyid' => $_SESSION['familyid']]);
$familyname = $familyinfo['familyname'];
$fathername = $familyinfo['fathername'];
$mothername = $familyinfo['mothername'];
$streetaddress = $familyinfo['address'];
$city = $familyinfo['city'];
$state = $familyinfo['state'];
$zip = $familyinfo['zip'];
$phone = $familyinfo['phone'];
$email = $familyinfo['email'];
$newsletter_method = $familyinfo['newsletter_method'];
$campers = $database->select("people", 'personid', ['AND' => ['familyid' => $_SESSION['familyid'], 'camperid[!]' => null]]);
$adults = $database->select("people", 'personid', ['AND' => ['familyid' => $_SESSION['familyid'], 'adultid[!]' => null]]);
$youth = $database->select("people", 'personid', ['AND' => ['familyid' => $_SESSION['familyid'], 'youthid[!]' => null]]);
}
?>
<div class="container mt-4">
<form action="actions/submitmembership.php" method="post" id="membershipform">
<form action="actions/submit.php" method="post" id="registrationform">
<?php
// Add a hidden form element, to detect if the renewal session
// expired before we submitted the thing
if (isset($_SESSION['familyid'])) {
?>
<input type="hidden" name="renewing" value="1" />
<input type="hidden" name="editing" value="1" />
<?php
}
?>
<div class="card mb-4">
<div class="card mb-4 bg-green text-light">
<div class="card-body">
<div class="d-flex flex-wrap justify-content-around">
<img class="img-fluid" style="max-height: 100px; min-width: 100px;" src="static/hachelogo.svg" alt="HACHE: Helena Area Christian Home Educators"/>
<div class="ml-auto mr-auto pl-4 align-self-center text-center">
<?php
if (isset($_SESSION['familyid'])) {
echo "<h1>Membership Renewal</h1>";
} else {
echo "<h1>Membership Application</h1>";
}
?>
<h1>Day Camp Registration</h1>
</div>
</div>
</div>
@ -78,393 +53,97 @@ if (isset($_SESSION['familyid']) && $database->has('families', ['familyid' => $_
}
?>
<!-- Campers -->
<div class="card mb-4">
<div class="card-header">
<h3><i class="fas fa-info fa-fw"></i> Basic Information</h3>
<div class="card-header bg-green text-light">
<h3><i class="fas fa-campground fa-fw"></i> Campers</h3>
</div>
<div class="card-body">
<div class="row">
<?php
$textboxes = [
[
"label" => "Family Name (Last Name)",
"icon" => "fas fa-users",
"name" => "familyname",
"maxlength" => 100,
"value" => $familyname,
"error" => "Enter your last name."
],
[
"label" => "Father's Name",
"icon" => "fas fa-male",
"name" => "fathername",
"maxlength" => 255,
"value" => $fathername,
"error" => "Enter the father's name."
],
[
"label" => "Mother's Name",
"icon" => "fas fa-female",
"name" => "mothername",
"maxlength" => 255,
"value" => $mothername,
"error" => "Enter the mother's name."
],
[
"label" => "Street Address",
"icon" => "fas fa-home",
"name" => "streetaddress",
"maxlength" => 500,
"value" => $streetaddress,
"error" => "Enter your address."
],
[
"label" => "City",
"icon" => "fas fa-city",
"name" => "city",
"maxlength" => 255,
"width" => 3,
"value" => $city,
"error" => "Enter your city."
],
[
"label" => "State",
"icon" => "fas fa-flag",
"name" => "state",
"type" => "select",
"value" => $state,
"error" => "Choose a state.",
"options" => [
'MT' => 'Montana',
'AL' => 'Alabama',
'AK' => 'Alaska',
'AZ' => 'Arizona',
'AR' => 'Arkansas',
'CA' => 'California',
'CO' => 'Colorado',
'CT' => 'Connecticut',
'DE' => 'Delaware',
'DC' => 'District of Columbia',
'FL' => 'Florida',
'GA' => 'Georgia',
'HI' => 'Hawaii',
'ID' => 'Idaho',
'IL' => 'Illinois',
'IN' => 'Indiana',
'IA' => 'Iowa',
'KS' => 'Kansas',
'KY' => 'Kentucky',
'LA' => 'Louisiana',
'ME' => 'Maine',
'MD' => 'Maryland',
'MA' => 'Massachusetts',
'MI' => 'Michigan',
'MN' => 'Minnesota',
'MS' => 'Mississippi',
'MO' => 'Missouri',
'MT' => 'Montana',
'NE' => 'Nebraska',
'NV' => 'Nevada',
'NH' => 'New Hampshire',
'NJ' => 'New Jersey',
'NM' => 'New Mexico',
'NY' => 'New York',
'NC' => 'North Carolina',
'ND' => 'North Dakota',
'OH' => 'Ohio',
'OK' => 'Oklahoma',
'OR' => 'Oregon',
'PA' => 'Pennsylvania',
'RI' => 'Rhode Island',
'SC' => 'South Carolina',
'SD' => 'South Dakota',
'TN' => 'Tennessee',
'TX' => 'Texas',
'UT' => 'Utah',
'VT' => 'Vermont',
'VA' => 'Virginia',
'WA' => 'Washington',
'WV' => 'West Virginia',
'WI' => 'Wisconsin',
'WY' => 'Wyoming'
],
"width" => 2
],
[
"label" => "ZIP/Postal Code",
"icon" => "fas fa-mail-bulk",
"name" => "zip",
"maxlength" => 10,
"width" => 3,
"value" => $zip,
"pattern" => "[0-9]{5}(-?[0-9]{4})?",
"error" => "Enter a valid 5 or 9 digit ZIP code."
],
[
"label" => "Phone Number",
"icon" => "fas fa-phone",
"name" => "phone",
"type" => "tel",
"maxlength" => 20,
"value" => $phone,
"pattern" => "[0-9]{10}",
"error" => "Enter a 10-digit phone number (numbers only)."
],
[
"label" => "Email",
"icon" => "fas fa-at",
"name" => "email",
"maxlength" => 255,
"type" => "email",
"value" => $email,
"error" => "Enter your email address."
],
[
"label" => "Newsletter Preference",
"icon" => "fas fa-newspaper",
"name" => "newsletter_method",
"type" => "select",
"value" => $newsletter_method,
"options" => [
"1" => "Email ($25)",
"2" => "Paper ($35)",
"3" => "Email and Paper ($35)"
],
"error" => "Choose a newsletter option."
]
];
foreach ($textboxes as $item) {
?>
<div class="col-12 col-md-<?php echo (empty($item['width']) ? "4" : $item['width']); ?>">
<div class="form-group mb-3">
<label class="mb-0"><?php echo $item['label']; ?>:</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="<?php echo $item['icon']; ?>"></i></span>
</div>
<?php if (empty($item['type']) || $item['type'] != "select") { ?>
<input type="<?php echo (empty($item['type']) ? "text" : $item['type']); ?>"
name="<?php echo $item['name']; ?>"
class="form-control"
placeholder=""
aria-label="<?php echo $item['label']; ?>"
maxlength="<?php echo $item['maxlength']; ?>"
<?php
if (!empty($item['pattern'])) {
?>
pattern="<?php echo $item['pattern']; ?>"
<?php
}
?>
<?php
if (!empty($item['value'])) {
?>
value="<?php echo htmlspecialchars($item['value']); ?>"
<?php
}
?>required />
<?php } else if ($item['type'] == "select") { ?>
<select class="form-control"
name="<?php echo $item['name']; ?>"
aria-label="<?php echo $item['label']; ?>"
required>
<?php
foreach ($item['options'] as $value => $label) {
$selected = "";
if (!empty($item['value']) && $value == $item['value']) {
$selected = " selected";
}
echo "<option value=\"$value\"$selected>$label</option>\n";
}
?>
</select>
<?php
}
?>
<div class="invalid-feedback">
<?php echo $item['error']; ?>
</div>
</div>
</div>
</div>
<?php
<div class="list-group list-group-flush" id="camper_list">
<?php
$persontype = "camper";
if (count($campers) > 0) {
foreach ($campers as $personid) {
include __DIR__ . "/template_person.php";
}
?>
</div>
<div class="card-text">
<p>
The membership fees (determined by your newsletter
preference) cover costs of the following:
phone; website; postage; distribution of newsletters and
directories; publication of materials; library; and other
HACHE related activities. Dues are reduced as of March 1st.
HACHE will not restrict membership based on inability to
pay. HACHE does not mandate curriculum choices or the
manner in which curriculum is administered. We do encourage
all members to follow and adhere to MT laws governing home
schooling.
</div>
} else {
include __DIR__ . "/template_person.php";
}
?>
</div>
</div>
<div class="card mb-4">
<div class="card-header">
<h3><i class="fas fa-user-graduate fa-fw"></i> Children</h3>
</div>
<div class="card-body">
<div class="card-text">
<p>
Please list your children's first names and birth dates. This
information will appear in our members directory. Members
agree that they will NOT make this information public.
<div class="list-group" id="child_list">
<?php
if (count($children) > 0) {
foreach ($children as $childid) {
include __DIR__ . "/template_child_entry.php";
}
} else {
include __DIR__ . "/template_child_entry.php";
}
?>
</div>
<div class="btn btn-sm btn-primary mt-1" id="add_child_row">
<i class="fas fa-plus"></i> Add another
</div>
<div class="btn btn-sm btn-teal mt-1" id="add_camper">
<i class="fas fa-plus"></i> Add another
</div>
</div>
</div>
<!-- Adults -->
<div class="card mb-4">
<div class="card-header">
<h3><i class="fas fa-check-circle fa-fw"></i> Consent</h3>
<div class="card-header bg-green text-light">
<h3><i class="fas fa-hiking fa-fw"></i> Adult Volunteers</h3>
</div>
<div class="list-group list-group-flush" id="adult_list">
<?php
$persontype = "adult";
if (count($adults) > 0) {
foreach ($adults as $personid) {
include __DIR__ . "/template_person.php";
}
} else {
include __DIR__ . "/template_person.php";
}
?>
</div>
<div class="card-body">
<div class="card-text">
<p class="mb-0">HACHE members occasionally take pictures of students during
home school functions and activities. These photos may be
used in HACHE displays, brochures, website, etc.
<p>I give permission for my photos to be included in such displays:
<span class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="photo_permission" id="photo_permission" value="1" required>
<label class="form-check-label" for="photo_permission">Yes</label>
</span>
<span class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="photo_permission" id="photo_permission" value="0" required>
<label class="form-check-label" for="photo_permission">No</label>
</span>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="1" name="agree_terms" id="agree_terms" required>
<label class="form-check-label" for="agree_terms">
I/We have read and understand this application and agree to abide by HACHEs policy of common courtesy and respect for one another.
</label>
<div class="card-body">
<div class="btn btn-sm btn-teal mt-1" id="add_adult">
<i class="fas fa-plus"></i> Add another
</div>
</div>
</div>
<!-- Youth Volunteers -->
<div class="card mb-4">
<div class="card-header">
<h3>
<span class="fa-layers fa-fw">
<i class="fas fa-basketball-ball" data-fa-transform="shrink-5 up-4.5 left-4.5"></i>
<i class="fas fa-book" data-fa-transform="shrink-5 right-4.5 down-4.5"></i>
</span>
Activities
</h3>
<div class="card-header bg-green text-light">
<h3><i class="fas fa-walking fa-fw"></i> Youth Volunteers</h3>
</div>
<div class="card-body">
<div class="card-text">
<p>HACHE is an all-volunteer organization. Listed below are events
and activities that may occur throughout the year. If you are
interested in helping with one or more of these events please
select any and all events of interest so we can get you in touch
with the member in charge of said event. Please feel free to
contact Steering Committee members or the newsletter editor with
ideas for field trips and or other activities that may be
enjoyed by all. (Not all of these events are specifically
HACHE events, but rather events HACHE supported events our
members have participated in and enjoyed in past years.)
</div>
<div class="list-group list-group-flush" id="youth_list">
<?php
$events = $database->select('events', ['eventid (id)', 'event (name)']);
$eventcount = count($events);
$cola = [];
$colb = [];
for ($i = 0; $i < $eventcount; $i++) {
if ($i % 2 === 0) {
$cola[] = $events[$i];
} else {
$colb[] = $events[$i];
$persontype = "youth";
if (count($youth) > 0) {
foreach ($youth as $personid) {
include __DIR__ . "/template_person.php";
}
} else {
include __DIR__ . "/template_person.php";
}
?>
</div>
<div class="row">
<div class="col-12 col-md-6">
<ul class="list-group">
<?php
foreach ($cola as $ev) {
?>
<li class="list-group-item">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="events_<?php echo $ev['id']; ?>" value="<?php echo $ev['id']; ?>" name="events[]">
<label class="form-check-label" for="events_<?php echo $ev['id']; ?>"><?php echo $ev['name']; ?></label>
</div>
</li>
<?php
}
?>
</ul>
</div>
<div class="col-12 col-md-6">
<ul class="list-group">
<?php
foreach ($colb as $ev) {
?>
<li class="list-group-item">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="events_<?php echo $ev['id']; ?>" value="<?php echo $ev['id']; ?>" name="events[]">
<label class="form-check-label" for="events_<?php echo $ev['id']; ?>"><?php echo $ev['name']; ?></label>
</div>
</li>
<?php
}
?>
</ul>
</div>
<div class="card-body">
<div class="btn btn-sm btn-teal mt-1" id="add_youth">
<i class="fas fa-plus"></i> Add another
</div>
</div>
</div>
<!-- Payment -->
<div class="card mb-4">
<div class="card-header">
<div class="card-header bg-green text-light">
<h3><i class="fas fa-dollar-sign fa-fw"></i> Pay and Submit</h3>
</div>
<div class="card-body">
<h4>Total: $<span id="total">0</span></h4>
<noscript>
<div class="card-text text-danger mb-1">
<i class="fas fa-code"></i> JavaScript is required to complete your payment.
</div>
</noscript>
<div class="card-text text-success mb-1">
<i class="fas fa-lock"></i> We can't see your card info; it's sent directly and securely from your computer to our payment processor.
</div>
@ -478,9 +157,9 @@ if (isset($_SESSION['familyid']) && $database->has('families', ['familyid' => $_
<input type="hidden" name="stripeToken" id="stripe-token" required />
</div>
<div class="card-footer">
<button type="submit" class="btn btn-primary" id="savebutton">
<button type="submit" class="btn btn-teal" id="savebutton">
<span id="savebutton-text">
<i class="fas fa-arrow-right"></i> Submit<span class="d-none d-sm-inline"> Application and Payment</span>
<i class="fas fa-arrow-right"></i> Submit<span class="d-none d-sm-inline"> Registration and Payment</span>
</span>
<span id="savebutton-wait" class="d-none">
<i class="fas fa-spinner fa-spin"></i> Working...

@ -1,89 +0,0 @@
<?php
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
require_once __DIR__ . "/../../lib/requiredpublic.php";
$childinfo = ['name' => '', 'month' => 1, 'year' => date('Y', strtotime('now - 10 years')), 'graduated' => false];
if (isset($childid) && $database->has('people', ['personid' => $childid])) {
$randomid = $childid;
$chinfo = $database->get('people', ['name', 'birthday', 'graduated'], ['personid' => $childid]);
$childinfo['name'] = $chinfo['name'];
$childinfo['graduated'] = $chinfo['graduated'] == true;
$childinfo['month'] = date('m', strtotime($chinfo['birthday']));
$childinfo['year'] = date('Y', strtotime($chinfo['birthday']));
} else {
do {
$randomid = mt_rand(0, 9999999999);
} while ($database->has('people', ['personid' => $randomid]));
}
?>
<div class="list-group-item">
<input type="hidden" name="child[ids][]" value="<?php echo $randomid; ?>" />
<div class="row">
<div class="col-12 col-sm-4">
<div class="form-group">
<label>Name:</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-user-graduate"></i></span>
</div>
<input type="text" name="child[name][<?php echo $randomid; ?>]" class="form-control" value="<?php echo htmlspecialchars($childinfo['name']); ?>" />
</div>
</div>
</div>
<div class="col-12 col-sm-3">
<div class="form-group">
<label>Birth month:</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-calendar"></i></span>
</div>
<select name="child[month][<?php echo $randomid; ?>]" class="form-control" value="<?php echo $childinfo['month']; ?>" >
<?php
for ($i = 1; $i <= 12; $i++) {
$selected = "";
if ($childinfo['month'] == $i) {
$selected = " selected";
}
echo "<option value=$i$selected>" . date("F", mktime(0, 0, 0, $i, 2)) . "</option>\n";
}
?>
</select>
</div>
</div>
</div>
<div class="col-12 col-sm-3">
<div class="form-group">
<label>Birth year:</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-calendar-alt"></i></span>
</div>
<input type="number" name="child[year][<?php echo $randomid; ?>]" class="form-control" min="1980" max="<?php echo date('Y'); ?>" value="<?php echo $childinfo['year']; ?>"/>
</div>
</div>
</div>
<div class="col-12 col-sm-2">
<div class="form-group">
<label>&nbsp;</label>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="1" name="child[graduate][<?php echo $randomid; ?>]"<?php
if ($childinfo['graduated']) {
echo " checked";
}
?>>
<label class="form-check-label mt-1">Graduated</label>
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,267 @@
<?php
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
require_once __DIR__ . "/../../lib/requiredpublic.php";
// Get the person type, either from the URL or a preset variable in the including script
$type = "camper";
if (!empty($_GET["type"]) && preg_match("/^(camper|adult|youth)$/", $_GET["type"])) {
$type = $_GET["type"];
} else if (!empty($persontype)) {
$type = $persontype;
}
$personinfo = ["firstname" => "", "lastname" => "", "address" => "", "zip" => "", "phone1" => "", "phone2" => "", "email" => "", "unit" => "", "shirt" => ""];
switch ($type) {
case "camper":
$personinfo["parentname"] = "";
$personinfo["rank"] = "";
break;
case "youth":
$personinfo["parentname"] = "";
$personinfo["days"] = "";
$personinfo["position"] = "";
break;
case "adult":
$personinfo["days"] = "";
$personinfo["position"] = "";
$personinfo["child_care"] = "";
break;
}
foreach ($_GET as $key => $val) {
if (array_key_exists($key, $personinfo)) {
$personinfo[$key] = htmlentities($val);
}
}
if (isset($personid) && $database->has('people', ['personid' => $personid])) {
$personinfo = $database->get('people', '*', ['personid' => $personid]);
} else {
do {
$personid = mt_rand(0, 9999999999);
} while ($database->has('people', ['personid' => $personid]));
}
?>
<div class="list-group-item person-list-item" data-persontype="<?php echo $type; ?>">
<input type="hidden" name="people[ids][]" value="<?php echo $personid; ?>" />
<input type="hidden" name="persontype" value="<?php echo $type; ?>" />
<div class="row">
<?php
$textboxes = [
[
"label" => "First Name",
"name" => "firstname",
"maxlength" => 255,
"width" => 6,
"value" => $personinfo["firstname"],
"error" => "Enter the person's first name."
],
[
"label" => "Last Name",
"name" => "lastname",
"width" => 6,
"maxlength" => 255,
"value" => $personinfo["lastname"],
"error" => "Enter the person's last name."
]
];
if ($type == "camper") {
$textboxes = array_merge($textboxes, [
[
"label" => "Parent/Guardian Name",
"name" => "parentname",
"width" => 12,
"maxlength" => 255,
"value" => $personinfo["parentname"],
"error" => "Enter the parent or guardian's full name."
]
]);
}
$textboxes = array_merge($textboxes, [
[
"label" => "Address",
"name" => "address",
"maxlength" => 500,
"width" => 8,
"value" => $personinfo["address"],
"error" => "Enter the person's home address."
],
[
"label" => "ZIP Code",
"name" => "zip",
"maxlength" => 10,
"width" => 4,
"value" => $personinfo["zip"],
"pattern" => "[0-9]{5}(-?[0-9]{4})?",
"error" => "Enter a valid 5 or 9 digit ZIP code."
],
[
"label" => "Phone Number",
"name" => "phone1",
"type" => "tel",
"maxlength" => 20,
"width" => 3,
"value" => $personinfo["phone1"],
"pattern" => "[0-9]{10}",
"error" => "Enter a 10-digit phone number (numbers only)."
],
[
"label" => "Email",
"name" => "email",
"maxlength" => 255,
"width" => 5,
"type" => "email",
"value" => $personinfo["email"],
"error" => "Enter your email address."
]
]);
if ($type == "camper") {
$textboxes = array_merge($textboxes, [
[
"label" => "Pack #",
"name" => "unit",
"width" => 2,
"maxlength" => 4,
"pattern" => "[0-9]{3,4}",
"value" => $personinfo["unit"],
"error" => "Enter the pack number."
],
[
"label" => "Rank",
"name" => "rank",
"type" => "select",
"width" => 2,
"value" => $personinfo["rank"],
"options" => [
"" => "Choose...",
"Tiger" => "Tiger",
"Wolf" => "Wolf",
"Bear" => "Bear",
"Webelos" => "Webelos",
"Arrow of Light" => "Arrow of Light",
],
"error" => "Choose a rank."
]
]);
}
if ($type == "youth") {
$textboxes = array_merge($textboxes, [
[
"label" => "Parent Name",
"name" => "parentname",
"width" => 4,
"maxlength" => 255,
"value" => $personinfo["parentname"],
"error" => "Enter the parent or guardian's full name."
],
[
"label" => "Parent Phone",
"name" => "phone2",
"type" => "tel",
"maxlength" => 20,
"width" => 3,
"value" => $personinfo["phone2"],
"pattern" => "[0-9]{10}",
"error" => "Enter a 10-digit phone number (numbers only)."
]
]);
}
if ($type == "adult" || $type == "youth") {
// TODO: camp days selection
// TODO: help area selection
}
$textboxes = array_merge($textboxes, [
[
"label" => "Shirt Size",
"name" => "shirt",
"type" => "select",
"value" => $personinfo["shirt"],
"options" => [
"" => "Choose...",
"YS" => "Youth Small",
"YM" => "Youth Medium",
"YL" => "Youth Large",
"AS" => "Adult Small",
"AM" => "Adult Medium",
"AL" => "Adult Large",
"AX" => "Adult Extra Large",
"A2" => "Adult 2X Large"
],
"error" => "Choose a shirt size."
]
]);
foreach ($textboxes as $item) {
?>
<div class="col-12 col-md-<?php echo (empty($item['width']) ? "4" : $item['width']); ?>">
<div class="form-group mb-3">
<label class="mb-0"><?php echo $item['label']; ?>:</label>
<div class="input-group">
<?php if (empty($item['type']) || $item['type'] != "select") { ?>
<input type="<?php echo (empty($item['type']) ? "text" : $item['type']); ?>"
name="<?php echo $item['name']; ?>"
class="form-control"
placeholder=""
aria-label="<?php echo $item['label']; ?>"
maxlength="<?php echo $item['maxlength']; ?>"
<?php
if (!empty($item['pattern'])) {
?>
pattern="<?php echo $item['pattern']; ?>"
<?php
}
?>
<?php
if (!empty($item['value'])) {
?>
value="<?php echo htmlspecialchars($item['value']); ?>"
<?php
}
if (empty($item['optional'])) {
echo "required";
}
?> />
<?php } else if ($item['type'] == "select") { ?>
<select class="form-control"
name="<?php echo $item['name']; ?>"
aria-label="<?php echo $item['label']; ?>"
<?php
if (empty($item['optional'])) {
echo "required";
}
?>>
<?php
foreach ($item['options'] as $value => $label) {
$selected = "";
if (!empty($item['value']) && $value == $item['value']) {
$selected = " selected";
}
echo "<option value=\"$value\"$selected>$label</option>\n";
}
?>
</select>
<?php
}
?>
<div class="invalid-tooltip">
<?php echo $item['error']; ?>
</div>
</div>
</div>
</div>
<?php
}
?>
</div>
</div>

@ -1,107 +0,0 @@
<?php
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
if (empty($IN_SITE)) {
die("Access denied.");
}
$badcode = false;
if (!empty($_POST['email'])) {
if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
header("Location: ./?page=renew&msg=bademail");
die("That email address doesn't look right. Please try again.");
}
if (!$database->has("families", ['email' => strtolower($_POST['email'])])) {
header("Location: ./?page=renew&msg=noemail");
die("We don't have that email on file for any current families.");
}
$familyid = $database->get('families', 'familyid', ['email' => strtolower($_POST['email'])]);
// Check expiration date
$expires = (new Family())->load($familyid)->getExpires();
if ($expires > strtotime("+6 months")) {
header("Location: ./?page=renew&msg=tooearly&exp=$expires");
die("This membership isn't expiring until " . date("F j, Y", $expires) . " and cannot be renewed yet.");
}
$code = mt_rand(100000, 999999);
$_SESSION['code'] = $code;
$_SESSION['maybefamily'] = $familyid;
try {
$verification = new Email();
$verification->addTo($SETTINGS["smtp"]["notification_to"]);
$verification->setFrom($SETTINGS["smtp"]["fromaddress"], $SETTINGS["smtp"]["fromname"]);
$verification->setSMTP($SETTINGS["smtp"]["host"], $SETTINGS["smtp"]["port"], $SETTINGS["smtp"]["auth"], $SETTINGS["smtp"]["user"], $SETTINGS["smtp"]["password"], $SETTINGS["smtp"]["secure"]);
$verification->setSubject("HACHE email verification");
$verification->setBody("The verification code for renewing your HACHE membership is $code.");
$verification->send();
} catch (Exception $e) {
}
} else if (!empty($_POST['code'])) {
if (empty($_SESSION['code'])) {
header("Location: ./?page=renew&msg=sessionexpired");
die("You took too long and were automatically logged out. Please try again.");
}
if (preg_replace("/[^0-9]/", "", $_POST['code']) == $_SESSION['code']) {
$_SESSION['familyid'] = $_SESSION['maybefamily'];
header("Location: ./?page=signup");
die("You are verified, go to ./?page=signup");
}
$badcode = true;
} else {
header("Location: ./?page=renew&msg=bademail");
die("That email address doesn't look right. Please try again.");
}
?>
<div class="container mt-4">
<div class="row justify-content-center">
<div class="card mb-4 col-lg-8">
<div class="card-body">
<div class="text-center">
<img class="img-fluid mb-4" style="max-height: 100px; min-width: 100px;" src="static/hachelogo.svg" alt="HACHE: Helena Area Christian Home Educators"/>
<h1>Renew Your Membership</h1>
<div class="card-text">
<p>
Enter the code from the email we just sent you.
If you didn't get it, check your spam or junk folder.
</div>
<?php
if ($badcode) {
?>
<div class="alert alert-danger">
The code you entered is incorrect.
</div>
<?php
}
?>
<form action="./?page=verify" method="POST">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">
<span class="fa-layers fa-fw mr-2">
<i class="fas fa-2x fa-hashtag"></i>
</span>
</span>
</div>
<input type="text" class="form-control" style="font-size: 40px; letter-spacing: 10px;" name="code" placeholder="000000" maxLength="6" autofocus />
<div class="input-group-append">
<button type="submit" class="btn btn-primary">Verify <i class="fas fa-chevron-right"></i></button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 65 KiB

File diff suppressed because one or more lines are too long

@ -4,13 +4,68 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
$("#add_camper").click(function () {
var copyfrom = $("#camper_list .person-list-item").first();
$.get("parts/template_person.php", {
type: "camper",
lastname: $("input[name=lastname]", copyfrom).val(),
parentname: $("input[name=parentname]", copyfrom).val(),
address: $("input[name=address]", copyfrom).val(),
zip: $("input[name=zip]", copyfrom).val(),
phone1: $("input[name=phone1]", copyfrom).val(),
phone2: $("input[name=phone2]", copyfrom).val(),
email: $("input[name=email]", copyfrom).val(),
unit: $("input[name=unit]", copyfrom).val()
}, function (resp) {
$("#camper_list").append(resp);
updateTotal();
});
});
$("#add_adult").click(function () {
var copyfrom = $("#adult_list .person-list-item").first();
$.get("parts/template_person.php", {
type: "adult",
lastname: $("input[name=lastname]", copyfrom).val(),
address: $("input[name=address]", copyfrom).val(),
zip: $("input[name=zip]", copyfrom).val(),
phone1: $("input[name=phone1]", copyfrom).val(),
phone2: $("input[name=phone2]", copyfrom).val(),
email: $("input[name=email]", copyfrom).val()
}, function (resp) {
$("#adult_list").append(resp);
updateTotal();
});
});
$("#add_child_row").click(function () {
$.get("parts/template_child_entry.php", {}, function (resp) {
$("#child_list").append(resp);
$("#add_youth").click(function () {
var copyfrom = $("#youth_list .person-list-item").first();
$.get("parts/template_person.php", {
type: "youth",
lastname: $("input[name=lastname]", copyfrom).val(),
address: $("input[name=address]", copyfrom).val(),
zip: $("input[name=zip]", copyfrom).val(),
parentname: $("input[name=parentname]", copyfrom).val(),
phone2: $("input[name=phone2]", copyfrom).val(),
email: $("input[name=email]", copyfrom).val()
}, function (resp) {
$("#youth_list").append(resp);
updateTotal();
});
});
$("#camper_list").on("change", "input[name=firstname]", function () {
updateTotal();
});
function updateTotal() {
totalcharge = $(".person-list-item[data-persontype=camper] input[name=firstname]").filter(function () {
return $(this).val() != '';
}).length * 50.0;
$("#total").text(totalcharge);
}
// Create a Stripe client.
var stripe = Stripe(stripe_pubkey);
@ -34,18 +89,22 @@ card.addEventListener('change', function (event) {
});
$("#savebutton").click(function (event) {
var form = $("#membershipform");
var form = $("#registrationform");
console.log("Validating...");
if (form[0].checkValidity() === false) {
console.log("Invalid!");
event.preventDefault()
event.stopPropagation()
}
form.addClass('was-validated');
});
$("#membershipform").on("submit", function (event) {
$("#registrationform").on("submit", function (event) {
event.preventDefault();
// prevent multiple clicks since Stripe can take a few seconds
$("#savebutton").prop("disabled", true);
$("#savebutton-text").addClass("d-none");

File diff suppressed because one or more lines are too long

@ -0,0 +1,17 @@
/*
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/*
Created on : Mar 2, 2019, 8:47:19 PM
Author : Skylar Ittner
*/
body, html {
background-color: #004D40;
}
.person-list-item {
border: 1.5px solid var(--teal);
}

@ -19,14 +19,14 @@ $SETTINGS = [
// See http://medoo.in/api/new for info
"database" => [
"type" => "mysql",
"name" => "hachemembers",
"name" => "campportal",
"server" => "localhost",
"user" => "",
"password" => "",
"charset" => "utf8"
],
// Name of the app.
"site_title" => "Membership Portal",
"site_title" => "Camp Portal",
"stripe" => [
"pubkey" => "",
"seckey" => ""

Loading…
Cancel
Save