Please navigate the site linked here to see these achievements first-hand.

Frontend UI

The program contains validations for user inputs in both the frontend and the backend.

Frontend Validation

The validation in the frontend runs based on these conditions:

Description Image
All fields must be filled in. Code segment shows list being formed
Name, email, event name and event details must all be less than 100 characters to prevent spam. Code segment shows list being formed
The date inputted must be in the future, but cannot be more than a year in the future. Code segment shows list being formed
The start and end time of the event must be during the open hours (listed on the "Hours" page). Code segment shows list being formed
The event cannot last longer than 3 hours so that the events room isn't too booked all the time. They must be at least 15 minutes long. Code segment shows list being formed
Name, email, event name, and password must not be duplicates. Code segment shows list being formed

Additionally, no more than five events can coincide within a time period at a time. There aren't that many events in the database, so producing an example alert would be difficult and essentially necessitate spam.

Create, Read Options

The create (POST) option exists in the form of the input boxes that let you add an event.

Code segment shows list being formed

The read (GET) option is the table below it

Code segment shows list being formed

BONUS: Delete Option

Above the table, a set of input boxes to delete an event allow you to do so if you input the event name and password.

Code segment shows list being formed

Backend Database

This section focuses on the backend code. You can use the table of contents at the top to skip to raw backend code.

Code Quality and Comments

In order to really see this, skip to the "Raw Code -> Backend Python Code". I put at least a few comments on every function and class.

Supporting Create and Read

Below is the model code code.

def create(self):
        try:
            # creates a person object from User(db.Model) class, passes initializers
            db.session.add(self)  # add prepares to persist person object to Users table
            db.session.commit()  # SqlAlchemy "unit of work pattern" requires a manual commit
            return self
        except IntegrityError:
            db.session.remove()
            return None

And below this is the read code.

def read(self):
        return {
            "id": self.id,
            "name": self.name,
            "email": self.email,
            "event_name": self.event_name,
            "event_details": self.event_details,
            "date": self.date,
            "start_time": self.start_time,
            "end_time": self.end_time,
            "password": self.password
        }

API GET and POST Methods

The POST method is seen below.

class _Create(Resource):
        def post(self):
            ''' Read data for json body '''
            body = request.get_json()
            
            ''' Avoid garbage in, error checking '''
            # validate name
            name = body.get('name')
            if name is None or len(name) < 2:
                return {'message': f'Submitter\'s name is missing, or is less than 2 characters'}, 210
            # validate uid
            email = body.get('email')
            if email is None or len(email) < 2:
                return {'message': f'Email is missing, or is less than 2 characters'}, 210
            # look for the rest of the data
            event_name = body.get('event_name')
            event_details = body.get('event_details')
            date = body.get('date')
            if (date is None) or (len(date) != 10) or (int(date[6:10]) < 2023) or (int(date[6:10]) > 2024):
                return {'message': f'Date is missing, formatted incorrectly, or within an invalid time range.'}, 210
            start_time = body.get('start_time')
            end_time = body.get('end_time')
            password = body.get('password')

            ''' #1: Key code block, setup USER OBJECT '''
            eo = Event(name=name, 
                      email=email,
                      event_name=event_name,
                      event_details=event_details,
                      date=date,
                      start_time=start_time,
                      end_time=end_time,
                      password=password)
            
            ''' #2: Key Code block to add user to database '''
            # create user in database
            event = eo.create()
            # success returns json of user
            if event:
                return jsonify(event.read())
            # failure returns error
            return {'message': f'Processed {event_name}, either a format error or the event "{event_name}" is a duplicate'}, 210

And below this is the GET.

class _Read(Resource):
        def get(self):
            events = Event.query.all()    # read/extract all users from database
            json_ready = [event.read() for event in events]  # prepare output in json
            return jsonify(json_ready)  # jsonify creates Flask response object, more specific to APIs than json.dumps

BONUS: Delete Method

Below is the additional delete method, which has been connected to the frontend as shown above.

class _Delete(Resource):
        def delete(self):
            body = request.get_json() #getting the database data for a given event
            event_id = body.get('id') #isolating the ID of the given entry
           
            status = deleteID(event_id) #uses the deleteID function from the model
            if status:
                return {'message': f'Successfully deleted event with id {event_id} '}
            else:
                return {'message': f'Event with id {event_id} not found'}, 240

Raw Code

So that it is all accessible, I figured I would include all of the relevant files for my part of the project.

Frontend Javascript Code

Here is all the code that goes into the frontend. See the comments throughout to understand what is being done and why.

let sorted = false;
var pulldata = "";

const read_url = "https://cgato.duckdns.org/api/events";
const read_options = {
    method: 'GET', // *GET, POST, PUT, DELETE, etc.
    mode: 'cors', // no-cors, *cors, same-origin
    cache: 'default', // *default, no-cache, reload, force-cache, only-if-cached
    credentials: 'omit', // include, *same-origin, omit
    headers: {
    'Content-Type': 'application/json'
    // 'Content-Type': 'application/x-www-form-urlencoded',
    },
};
const post_url = "https://cgato.duckdns.org/api/events/create";
const del_url = "https://cgato.duckdns.org/api/events/delete";

const table = document.getElementById("evtablecont");

function showEvTable() {
    create_Table();
    document.getElementById('evlogbtn').style = "display:none";
    document.getElementById('logrefbtn').style = "display:block";
    document.getElementById('delControls').style = "display:block";
    document.getElementById('event_name_del').style = "display:block";
    document.getElementById('password_del').style = "display:block";
    document.getElementById('deletebtn').style = "display:block";
    document.getElementById('evtable').style = "display:block";
    document.getElementById('filters').style = "font-size:25px;display:block";
}

function time_Dif(start, end) {
    var hourdif = 60 * (Number(end.substring(0, 2)) - Number(start.substring(0, 2)));
    var mindif = Number(end.substring(3, 5)) - Number(start.substring(3, 5));
    return hourdif + mindif
}

// THIS IS A PLACEHOLDER FUNCTION FOR WHEN THE API IS RUNNING
function submit_Form() {
    try {
        fetch(read_url, read_options)
            // response is a RESTful "promise" on any successful fetch
            .then(response => {
            // check for response errors
            if (response.status !== 200) {
                const errorMsg = 'Database response error: ' + response.status;
                console.log(errorMsg);
            };
            // valid response will have json data
            response.json().then(data => {
                var form_list = [document.getElementById('name').value, document.getElementById('email').value, document.getElementById('event_name').value, document.getElementById('event_details').value, document.getElementById('date').value, document.getElementById('start_time').value, document.getElementById('end_time').value, document.getElementById('password').value];
                // for loop to ensure all fields were filled in
                for (let i = 0; i < form_list.length; i++) {
                    if (form_list[i] == '') {
                        alert("There was an error processing your form. Make sure all fields are filled in.");
                        return;
                    };
                };
                for (let i = 0; i < 4; i++) {
                    if (form_list[i].length > 100) {
                        alert("There was an error processing your form. Certain input fields have too many characters. Make sure that your name, email, event name, and details are all no more than 100 characters long. (This is a measure to prevent spam.)")
                        return;
                    };
                };
                // Defining some variables for validation
                var tempdate = document.getElementById('date').value;
                var tempstime = document.getElementById('start_time').value;
                var tempetime = document.getElementById('end_time').value;
                var datefix = tempdate.substr(5, 2) + '/' + tempdate.substr(8, 10) + '/' + tempdate.substr(0, 4);
                const hourdict = [{"open":10, "close":18}, {"open":8, "close":17}, {"open":8, "close":17}, {"open":8, "close":17}, {"open":8, "close":17}, {"open":8, "close":17}, {"open":10, "close":18}];
                form_list[4] = datefix;
                var fulldate = datefix + " " + tempstime;
                let ev_date = new Date(fulldate);
                let cur_date = new Date();
                console.log(ev_date, cur_date);
                let ev_dow = ev_date.getDay()
                // validating date
                var datedif = Math.ceil((ev_date - cur_date) / (1000 * 60 * 60 * 24));
                if (1 > datedif || 365 < datedif) {
                    alert("There was an error processing your form. Make sure the date you have inputted is less than a year in the future.");
                    return;
                };
                // validating day of the week considering open hours
                if (Number(tempstime.substring(0, 2)) < hourdict[ev_dow]["open"] || Number(tempstime.substring(0, 2)) >= hourdict[ev_dow]["close"]) {
                    alert("There was an error processing your form. It seems that your event starts before opening/after closing on " + datefix + ".");
                    return;
                } else if (Number(tempetime.substring(0, 2)) <= hourdict[ev_dow]["open"] || Number(tempetime.substring(0, 2)) > hourdict[ev_dow]["close"]) {
                    alert("There was an error processing your form. It seems that your event ends before opening/after closing on " + datefix + ".");
                    return;
                };
                // validating event duration (must be at least 15 minutes, less than 3 hours, start must be before end)
                var timedif = time_Dif(tempstime, tempetime); //in minutes
                if (timedif < 15 || timedif > 180) {
                    alert("There was an error processing your form. Make sure that your event lasts at least 15 minutes, but no more than 3 hours.")
                    return;
                };
                // validating coincidence and email
                var coinc = 0;
                for (let i = 0; i < data.length; i++) {
                    temppull = data[i];
                    if (temppull['date'] == datefix) {
                        if (Number(tempstime.substring(0, 2)) <= Number(temppull['start_time'].substr(0, 2)) < Number(tempetime.substring(0, 2)) || Number(tempstime.substring(0, 2)) < Number(temppull['end_time'].substr(0, 2)) <= Number(tempetime.substring(0, 2))) {coinc = coinc + 1;};
                    };
                    if (temppull['email'] == form_list[1]) {
                        alert("There was an error processing your form. It seems that an event has already been created by that email. If someone has used your address to create an event without your consent, contact our staff.");
                        return;
                    };
                };
                if (coinc > 5) {
                    alert("There was an error processing your form. Make sure that your event's timing does not coincide with the timing of more than five other events.");
                    return;
                };
                // if all validations successful
                const body = {
                    "name": document.getElementById('name').value,
                    "email": document.getElementById('email').value,
                    "event_name": document.getElementById('event_name').value,
                    "event_details": document.getElementById('event_details').value,
                    "date": datefix,
                    "start_time": document.getElementById('start_time').value,
                    "end_time": document.getElementById('end_time').value,
                    "password": document.getElementById('password').value
                };
                const post_options = {
                    method: 'POST',
                    body: JSON.stringify(body),
                    headers: {
                        'Content-Type':'application/json',
                        'Authorization': 'Bearer my-token',
                    },
                };
                console.log(body);
                fetch(post_url, post_options)
                    .then(response =>
                        response.json().then(data => {
                            console.log(data);
                        })
                    )
                alert("Thank you, " + form_list[0] + ", for submitting an event! Watch your email for a confirmation message.\n\n(Warning: Please do not submit two events at a time! Your events may end up being cancelled as a result.)");
            });
        });
    } catch (err) {
        alert("There was an error processing your form. (Failed to send to/pull from the database, or there was an error in the formatting of your form. Make sure you're on unrestricted WiFi.)");
    };
};

// prepare HTML result container for new output
function create_Table() {
    // fetch the API
    fetch(read_url, read_options)
        // response is a RESTful "promise" on any successful fetch
        .then(response => {
        // check for response errors
        if (response.status !== 200) {
            const errorMsg = 'Database response error: ' + response.status;
            console.log(errorMsg);
        }
        // valid response will have json data
        response.json().then(data => {table_Make(data)})
    });
};

function table_Make(list) {
    table.innerHTML = "";
    list.forEach(user => {
            // build a row for each user
            const tr = document.createElement("tr");

            // td's to build out each column of data
            const name = document.createElement("td");
            const email = document.createElement("td");
            const event_name = document.createElement("td");
            const event_details = document.createElement("td");
            const date = document.createElement("td");
            const start_time = document.createElement("td");
            const end_time = document.createElement("td");
                
            // filter times
            var temp_stime = user.start_time;
            var temp_etime = user.end_time;
            if (Number(temp_stime.substring(0, 2)) > 12) {
                var temp_shr = Number(temp_stime.substring(0, 2)) - 12;
                var new_stime = String(temp_shr) + temp_stime.substring(2, 5) + " PM";
            } else {
                var new_stime = temp_stime + " AM"
            }
            if (Number(temp_etime.substring(0, 2)) > 12) {
                var temp_ehr = Number(temp_etime.substring(0, 2)) - 12;
                var new_etime = String(temp_ehr) + temp_etime.substring(2, 5) + " PM";
            } else {
                var new_etime = temp_etime + " AM"
            }

            // add content from user data          
            name.innerHTML = user.name; 
            email.innerHTML = user.email; 
            event_name.innerHTML = user.event_name; 
            event_details.innerHTML = user.event_details;
            date.innerHTML = user.date; 
            start_time.innerHTML = new_stime; 
            end_time.innerHTML = new_etime;

            // add data to row
            tr.appendChild(name);
            tr.appendChild(email);
            tr.appendChild(event_name);
            tr.appendChild(event_details);
            tr.appendChild(date);
            tr.appendChild(start_time);
            tr.appendChild(end_time);

            // add row to table
            table.appendChild(tr);
    });
};

var soonval = "placeholder";
var soon_fulldate = "placeholder";
var temp_soondate = "placeholder";
var lateval = "placeholder";
var late_fulldate = "placeholder";
var temp_latedate = "placeholder";

function sort_Events() {
    var orderval = document.getElementById("timesort").value;
    var monthval = document.getElementById("monthfil").value;
    var sorted_List = [];
    // fetch the API
    fetch(read_url, read_options)
        // response is a RESTful "promise" on any successful fetch
        .then(response => {
        // check for response errors
        if (response.status !== 200) {
            const errorMsg = 'Database response error: ' + response.status;
            console.log(errorMsg);
        };
        // valid response will have json data
        response.json().then(data => {
            var testcopy = [...data];
            var d_length = testcopy.length;
            if (orderval == "time_submitted") {
                        testcopy.forEach(event => {sorted_List.push(event)});
            } else if (orderval == "soonest") {
                for (let j = 0; j < d_length; j++) {
                    let i = 0;
                    testcopy.forEach(event => {
                        if (i == 0) {
                            soon_fulldate = event['date'] + " " + event['start_time'];
                            temp_soondate = new Date(soon_fulldate);
                            soonval = event;
                        } else {
                            var temp_fulldate = event['date'] + " " + event['start_time'];
                            var temp_evdate = new Date(temp_fulldate);
                            if (temp_evdate.getTime() < temp_soondate.getTime()) {
                                soon_fulldate = event.date + " " + event.start_time;
                                temp_soondate = new Date(soon_fulldate);
                                soonval = event;
                            };
                        };
                        i = i + 1;
                    });
                    sorted_List.push(soonval);
                    for (let i = 0; i < testcopy.length; i++) {
                        if (testcopy[i] == soonval) {
                            testcopy.splice(i, 1);
                        };
                    };
                };
            } else if (orderval == "latest") {
                for (let j = 0; j < d_length; j++) {
                    let i = 0;
                    testcopy.forEach(event => {
                        if (i == 0) {
                            late_fulldate = event['date'] + " " + event['start_time'];
                            temp_latedate = new Date(late_fulldate);
                            lateval = event;
                        } else {
                            var temp_fulldate = event['date'] + " " + event['start_time'];
                            var temp_evdate = new Date(temp_fulldate);
                            if (temp_evdate.getTime() > temp_latedate.getTime()) {
                                late_fulldate = event.date + " " + event.start_time;
                                temp_latedate = new Date(late_fulldate);
                                lateval = event;
                            };
                        };
                        i = i + 1;
                    });
                    sorted_List.push(lateval);
                    for (let i = 0; i < testcopy.length; i++) {
                        if (testcopy[i] == lateval) {
                            testcopy.splice(i, 1);
                        };
                    };
                };
            };
            var final_List = [];
            for (let k = 0; k < sorted_List.length; k++) {
                if (sorted_List[k]['date'].substring(6, 10) == monthval.substring(0, 4)) {
                    if (sorted_List[k]['date'].substring(0, 2) == monthval.substring(5, 7)) {final_List.push(sorted_List[k])} else {};
                } else {};
            };
            table_Make(final_List);
        });
    });
};

function delete_Event() {
    var del_ename = document.getElementById("event_name_del").value;
    var del_password = document.getElementById("password_del").value;
    var success = false;
    fetch(read_url, read_options)
        // response is a RESTful "promise" on any successful fetch
        .then(response => {
        // check for response errors
        if (response.status !== 200) {
            const errorMsg = 'Database response error: ' + response.status;
            console.log(errorMsg);
        };
        // valid response will have json data
        response.json().then(data => {
            data.forEach(event => {
                if (event['event_name'] == del_ename && event['password'] == del_password) {
                    // if all validations successful
                    const del_ID = event['id'];
                    const body = {
                        'id':del_ID
                    };
                    const del_options = {
                        method: 'DELETE',
                        body: JSON.stringify(body),
                        headers: {
                            'Content-Type':'application/json',
                            'Authorization': 'Bearer my-token',
                        },
                    };
                    console.log(body);
                    fetch(del_url, del_options)
                        .then(response =>
                            response.json().then(data => {
                                console.log(data);
                            })
                        )
                    alert('You have successfully deleted the event "' + event['event_name'] + '" from the events database.');
                    success = true;
                }
            })
            if (success == false) {alert("There was an error in one of the two fields you have filled in. Make sure that your event name and password both match the case used when first created. (You can copy-paste the event name from the data below.)")}
        })
    })
}

Backend Python Code

This is the code behind our backend server. It is primarily responsible for running the database we use.

Events Model Code

""" database dependencies to support sqliteDB examples """
from random import randrange
from datetime import date
import os, base64
import json

from __init__ import app, db
from sqlalchemy.exc import IntegrityError


''' Tutorial: https://www.sqlalchemy.org/library.html#tutorials, try to get into Python shell and follow along '''

# Define the User class to manage actions in the 'users' table
# -- Object Relational Mapping (ORM) is the key concept of SQLAlchemy
# -- a.) db.Model is like an inner layer of the onion in ORM
# -- b.) User represents data we want to store, something that is built on db.Model
# -- c.) SQLAlchemy ORM is layer on top of SQLAlchemy Core, then SQLAlchemy engine, SQL
class Event(db.Model):
    __tablename__ = 'events'  # table name is plural, class name is singular

    # Define the User schema with "vars" from object
    id = db.Column(db.Integer, primary_key=True)
    _name = db.Column(db.String(255), unique=False, nullable=False)
    #_uid = db.Column(db.String(255), unique=True, nullable=False)
    _email = db.Column(db.String(255), unique=False, nullable=False)
    _event_name = db.Column(db.String(255), unique=False, nullable=False)
    _event_details = db.Column(db.String(255), unique=False, nullable=False)
    _date = db.Column(db.String(255), unique=False, nullable=False)
    _start_time = db.Column(db.String(255), unique=False, nullable=False)
    _end_time = db.Column(db.String(255), unique=False, nullable=False)
    _password = db.Column(db.String(255), unique=False, nullable=False)

    # constructor of a User object, initializes the instance variables within object (self) 
    def __init__(self, name, email, event_name, event_details, date, start_time, end_time, password):
        self._name = name
        self._email = email
        self._event_name = event_name
        self._event_details = event_details
        self._date = date
        self._start_time = start_time
        self._end_time = end_time
        self._password = password
    
    #here's the name getter
    @property
    def name(self):
        return self._name

    #here's the name setter
    @name.setter
    def name(self, name):
        self._name = name
    
    #here's the email getter
    @property
    def email(self):
        return self._email
    
    #here's the email setter
    @email.setter
    def email(self, email):
        self._email = email
    
    #here's the event_name getter
    @property
    def event_name(self):
        return self._event_name
    
    #here's the event_name setter
    @event_name.setter
    def event_name(self, event_name):
        self._event_name = event_name
    
    #here's the event_details getter
    @property
    def event_details(self):
        return self._event_details
    
    #here's the event_details setter
    @event_details.setter
    def event_details(self, event_details):
        self._event_details = event_details
    
    #here's the date getter
    @property
    def date(self):
        return self._date
    
    #here's the date setter
    @date.setter
    def date(self, date):
        self._date = date

    #here's the start_time getter
    @property
    def start_time(self):
        return self._start_time
    
    #here's the start_time setter
    @start_time.setter
    def start_time(self, start_time):
        self._start_time = start_time

    #here's the end_time getter
    @property
    def end_time(self):
        return self._end_time
    
    #here's the end_time setter
    @end_time.setter
    def end_time(self, end_time):
        self._end_time = end_time

    #here's the password getter
    @property
    def password(self):
        return self._password
    
    #here's the password setter
    @password.setter
    def password(self, password):
        self._password = password
    
    # output content using str(object) in human readable form, uses getter
    # output content using json dumps, this is ready for API response
    def __str__(self):
        return json.dumps(self.read())

    # CRUD create/add a new record to the table
    # returns self or None on error
    def create(self):
        try:
            # creates a person object from User(db.Model) class, passes initializers
            db.session.add(self)  # add prepares to persist person object to Users table
            db.session.commit()  # SqlAlchemy "unit of work pattern" requires a manual commit
            return self
        except IntegrityError:
            db.session.remove()
            return None

    # CRUD read converts self to dictionary
    # returns dictionary
    def read(self):
        return {
            "id": self.id,
            "name": self.name,
            "email": self.email,
            "event_name": self.event_name,
            "event_details": self.event_details,
            "date": self.date,
            "start_time": self.start_time,
            "end_time": self.end_time,
            "password": self.password
        }

    # CRUD update: updates user name, password, phone
    # returns self
    def update(self, name="", email="", event_name="", event_details="", date="", start_time="", end_time="", password=""):
        """only updates values with length"""
        if len(name) > 0:
            self.name = name
        if len(email) > 0:
            self.email = email
        if len(event_name) > 0:
            self.event_name = event_name
        if len(event_details) > 0:
            self.event_details = event_details
        if len(date) > 0:
            self.date = date
        if len(start_time) > 0:
            self.start_time = start_time
        if len(end_time) > 0:
            self.end_time = end_time
        if len(password) > 0:
            self.password = password
        db.session.commit()
        return self

    # CRUD delete: remove self
    # None
    def delete(self):
        db.session.delete(self)
        db.session.commit()
        return None


"""Database Creation and Testing """


# Builds working data for testing
def initEvents():
    with app.app_context():
        """Create database and tables"""
        db.create_all()
        """Tester data for table
        e1 = Event(name="Thomas Edison", email="tedison@lightbulb.edu",
            event_name="The Edison Troupe Meet",
            event_details="We 10 selected geniuses will meet in the events room for a convergence.",
            date="02/23/2023", start_time="13:00", end_time="14:00", password="tedisonrules20")
        e2 = Event(name="John Mortensen", email="jmortensen@powayusd.com",
            event_name="Extra Credit Code Meetup",
            event_details="Come to work on ideation and any confusion with the Full Stack CPT project. No phones.",
            date="02/25/2023", start_time="10:00", end_time="12:00", password="codec0decod3bro")
        e3 = Event(name="Karl Giant", email="giantrichguy@wallstreet.org",
            event_name="Karl and Cats",
            event_details="Karl would like to see cats with friends (if he can fit in the building).",
            date="02/26/2023", start_time="16:00", end_time="17:00", password="i_am-the-f4th3r")
        
        events = [e1, e2, e3]

        #Builds sample events data
        for event in events:
            try:
                event.create()
            except IntegrityError:
                '''fails with bad or duplicate data'''
                db.session.remove()
                print(f"Records exist, duplicate data, or error: {event.event_name}")
        """

def deleteID(event_id):                
    event = Event.query.get(event_id) #getting an event from the database based on ID

    #user = Wordle.query.filter_by(name=name).first()
    if event != None:
        print("Query 1:", event) #prints the one query if it finds one
        db.session.delete(event) #deletes the event with the db.session innate function
        db.session.commit() #commits the change
        return True
    else:
        print("event "+str(event_id)+" not found") #if the event isn't found, the display is provided
        return False

Events API File

from flask import Flask, Blueprint, request, jsonify
from flask_restful import Api, Resource # used for REST API building
from datetime import *
from flask_cors import CORS

from model.events import Event, deleteID

event_api = Blueprint('event_api', __name__,
                   url_prefix='/api/events')

# API docs https://flask-restful.readthedocs.io/en/latest/api.html
api = Api(event_api)

class EventAPI:        
    class _Create(Resource):
        def post(self):
            ''' Read data for json body '''
            body = request.get_json()
            
            ''' Avoid garbage in, error checking '''
            # validate name
            name = body.get('name')
            if name is None or len(name) < 2:
                return {'message': f'Submitter\'s name is missing, or is less than 2 characters'}, 210
            # validate uid
            email = body.get('email')
            if email is None or len(email) < 2:
                return {'message': f'Email is missing, or is less than 2 characters'}, 210
            # look for the rest of the data
            event_name = body.get('event_name')
            event_details = body.get('event_details')
            date = body.get('date')
            if (date is None) or (len(date) != 10) or (int(date[6:10]) < 2023) or (int(date[6:10]) > 2024):
                return {'message': f'Date is missing, formatted incorrectly, or within an invalid time range.'}, 210
            start_time = body.get('start_time')
            end_time = body.get('end_time')
            password = body.get('password')

            ''' #1: Key code block, setup USER OBJECT '''
            eo = Event(name=name, 
                      email=email,
                      event_name=event_name,
                      event_details=event_details,
                      date=date,
                      start_time=start_time,
                      end_time=end_time,
                      password=password)
            
            ''' #2: Key Code block to add user to database '''
            # create user in database
            event = eo.create()
            # success returns json of user
            if event:
                return jsonify(event.read())
            # failure returns error
            return {'message': f'Processed {event_name}, either a format error or the event "{event_name}" is a duplicate'}, 210

    class _Read(Resource):
        def get(self):
            events = Event.query.all()    # read/extract all users from database
            json_ready = [event.read() for event in events]  # prepare output in json
            return jsonify(json_ready)  # jsonify creates Flask response object, more specific to APIs than json.dumps
    
    class _Delete(Resource):
        def delete(self):
            body = request.get_json() #getting the database data for a given event
            event_id = body.get('id') #isolating the ID of the given entry
           
            status = deleteID(event_id) #uses the deleteID function from the model
            if status:
                return {'message': f'Successfully deleted event with id {event_id} '}
            else:
                return {'message': f'Event with id {event_id} not found'}, 240

    # building RESTapi endpoint
    api.add_resource(_Create, '/create')
    api.add_resource(_Read, '/')
    api.add_resource(_Delete, '/delete')