diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..8a9375d Binary files /dev/null and b/.DS_Store differ diff --git a/app.py b/app.py index 299aadd..0e5030c 100644 --- a/app.py +++ b/app.py @@ -7,7 +7,7 @@ if __name__ == '__main__': # app.run(debug=True, host='0.0.0.0') - app.run(debug=True) + app.run(debug=True, port=5001) # mvc Model View Controller diff --git a/application/.DS_Store b/application/.DS_Store new file mode 100644 index 0000000..9409e26 Binary files /dev/null and b/application/.DS_Store differ diff --git a/application/__init__.py b/application/__init__.py index 5744f91..7b1c4fa 100644 --- a/application/__init__.py +++ b/application/__init__.py @@ -11,7 +11,7 @@ # Object is Python classes # Relational is MySQL # SQLAlchemy is the MAPPING layer between them -app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+pymysql://root:password@localhost/flask_team_a" +app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+pymysql://root:password@localhost/team_yellow" # app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+pymysql://username:password@host/database_name" # app.config['SQLALCHEMY_DATABASE_URI']=('mysql+pymysql://' + getenv('MYSQL_USER') + ':' + getenv('MYSQL_PASSWORD') + '@' + getenv('MYSQL_HOST') + '/' + getenv('MYSQL_DB')) app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False diff --git a/application/create.py b/application/create.py index 90a1163..20b980c 100644 --- a/application/create.py +++ b/application/create.py @@ -2,8 +2,18 @@ # the database # NOTE! The database MUST exist before we try to connect to it +# add one extra table for newsletter signup - just email + from application import db -from application.models import Person, Car +# from application.models import Person, Car # Victoria's code +from application.models import BlogPosts, Newsletter, PersonType, UserLogin, Address, StaffInfo, Person, OrderStatus, \ + Category, PlantType, Size,\ + Product, OrderHeader, OrderLine + +# Staff,Customer, +# these are the 12 tables we want to create in order: +# PersonType, UserLogin, Address, Person, OrderStatus, Category, PlantType, Size, Product, +# OrderHeader, OrderLine # create our database schema # db.create_all() @@ -11,22 +21,194 @@ db.drop_all() db.create_all() -testPerson1 = Person(first_name='Julie',last_name='Dooley') -testPerson2 = Person(first_name='Victoria',last_name='Lloyd') +# will need to use the db.session.add() code below to add the data - use lists as Victoria has below to make it easier? +# then need db.session.commit() to actually save it to the database +# once this code is populated, running it seperately should make everything appear in the database! + + +# Blogposts table +blog1 = BlogPosts(author='The Plant Doctor', date_posted='2022-01-01', title='Welcome', post_content='Hi, we are the ' + 'Plant Emporium, and we just want to welcome you to our shiny new website! It has taken a lot of blood, sweat and tears to get to this point and we cannot believe it is all actually working now.') +blog2 = BlogPosts(author='Master of the Retail Outlet', date_posted='2022-03-16', title='Exciting News', post_content='The shop is now officially open! We have a delightful new physical retail space, located in the heart of Sky Studios in Isleworth. After all the renovation work we have done, we cannot wait to show off the space! Come and see us to get your plant fix, we have some gorgeous stock and are happy to help you choose the perfect new planty companion.') +blog3 = BlogPosts(author='The Plant Doctor', date_posted='2022-04-30', title='Plant Clinic', post_content='We are now going to be running Sad Plant Fridays - post your ailing plants to Twitter #SadPlantFridays or email us at jody@theplantemporium.com and our resident Plant Doctor will diagnose the issue and more importantly, offer a solution! The Plant Doctor has years of experience in diagnosing and treating all manner of plant ailments, and firmly believes that we should Never Say Die! Well, unless the plant is really SUPER dead of course.') +blogs = [blog1, blog2, blog3] + +# Newsletter signup table +news1 = Newsletter(newsletter_email='ted.lasso@afc_richmond.co.uk') +news2 = Newsletter(newsletter_email='rebecca_welton@gmail.com') +news3 = Newsletter(newsletter_email='keeley_jones@gmail.com') +news4 = Newsletter(newsletter_email='roy.kent@afc_richmond.co.uk') +news5 = Newsletter(newsletter_email='sam.obisanya@afc_richmond.co.uk') +news = [news1, news2, news3, news4, news5] + +# PersonType table +person_type1 = PersonType(person_type_description='Staff') +person_type2 = PersonType(person_type_description='Customer') +person_types = [person_type1, person_type2] + +# user login without person type +user1 = UserLogin(username='tedlikesplants', password='1buyingaPLANT!') +user2 = UserLogin(username='rebecca_w', password='Panda42') +user3 = UserLogin(username='keeley.jones', password='passworDx4') +user4 = UserLogin(username='roy.kent', password='Richmond12') +user5 = UserLogin(username='sam_obisanya', password='FootballandPlants1') +user6 = UserLogin(username='natasha', password='staffaccess4') +user7 = UserLogin(username='jodie', password='staffaccess4') +user8 = UserLogin(username='jody', password='staffaccess4') +user9 = UserLogin(username='isabel', password='staffaccess4') +users = [user1, user2, user3, user4, user5, user6, user7, user8, user9] + + +# address table +address1 = Address(address_line_one='AFC Richmond Club House', address_line_two='Nelson Road', + address_line_three='London', postcode='TW9 4RP') +address2 = Address(address_line_one='49 Kings Road', address_line_two='Chelsea', address_line_three='London', + postcode='SW3 5TT') +address3 = Address(address_line_one='4 Portland Terrace', address_line_two='The Green', address_line_three='Richmond', + postcode='TW9 1QQ') +address4 = Address(address_line_one='The Plant Emporium', address_line_two='Sky Studios', postcode='TW7 5QD') +addresses = [address1, address2, address3, address4] + + +# staff info table +staff1 = StaffInfo(job_title='Plant purchaser', date_of_birth='1994-06-23') +staff2 = StaffInfo(job_title='Website wrangler', date_of_birth='1998-09-12') +staff3 = StaffInfo(job_title='Plant doctor', date_of_birth='1984-05-26') +staff4 = StaffInfo(job_title='Master of the retail outlet', date_of_birth='1999-08-16') +staff = [staff1, staff2, staff3, staff4] + +# person table +person1 = Person(first_name='Ted', last_name='Lasso', email='ted.lasso@afc_richmond.co.uk', address_id=1, + phone_number='07384957162', user_login_id=1, person_type_id=2) +person2 = Person(first_name='Rebecca', last_name='Welton', email='rebecca_welton@gmail.com', address_id=1, + phone_number='07492750173', user_login_id=2, person_type_id=2) +person3 = Person(first_name='Keeley', last_name='Jones', email='keeley_jones@gmail.com', address_id=2, + phone_number='07553630090', user_login_id=3, person_type_id=2) +person4 = Person(first_name='Roy', last_name='Kent', email='roy.kent@afc_richmond.co.uk', address_id=3, + phone_number='07554124856', user_login_id=4, person_type_id=2) +person5 = Person(first_name='Sam', last_name='Obisanya', email='sam.obisanya@afc_richmond.co.uk', address_id=1, + phone_number='07889578112', user_login_id=5, person_type_id=2) +person6 = Person(first_name='Natasha', last_name='Edun', email='natasha@plantemporium.com', address_id=4, + phone_number='07777777777',user_login_id=6, person_type_id=1, staff_info_id=1) +person7 = Person(first_name='Jodie', last_name='Smith', email='jodie@plantemporium.com', address_id=4, + phone_number='07777777777', user_login_id=7, person_type_id=1, staff_info_id=2) +person8 = Person(first_name='Jody', last_name='Broad', email='jody@plantemporium.com', address_id=4, + phone_number='07777777777', user_login_id=8, person_type_id=1, staff_info_id=3) +person9 = Person(first_name='Isabel', last_name='Tulloch', email='isabel@plantemporium.com', address_id=4, + phone_number='07777777777', user_login_id=9, person_type_id=1, staff_info_id=4) +persons = [person1, person2, person3, person4, person5, person6, person7, person8, person9] + + +# order status +status1 = OrderStatus(status_description='Ordered') +status2 = OrderStatus(status_description='Processing') +status3 = OrderStatus(status_description='Shipped') +status4 = OrderStatus(status_description='Collected') +status5 = OrderStatus(status_description='Returned') +status = [status1, status2, status3, status4, status5] -car1 = Car(number_plate='JU21DOO', person_id=1, colour='Red', make="Ferrari", model='V12') -car2 = Car(number_plate='JU20XXX', person_id=1, colour='Black', make="Mercedes-Benz", model='CLS') -car3 = Car(number_plate='VL21LLO', person_id=2, colour='Grey', make="Ford", model='Focus') -cars = [car1, car2, car3] -# car4 = Car(number_plate='BART21', person_id=3) +# category +category1 = Category(category_description='Indoor') +category2 = Category(category_description='Outdoor') +categories = [category1, category2] + + +# plant type table +plant1 = PlantType(plant_type_description='Cacti/Succulent') +plant2 = PlantType(plant_type_description='Hanging') +plant3 = PlantType(plant_type_description='Flowering') +plant4 = PlantType(plant_type_description='Palms') +plant5 = PlantType(plant_type_description='Ferns') +plant_types = [plant1, plant2, plant3, plant4, plant5] + + +# size +size1 = Size(size_description='Tiny') +size2 = Size(size_description='Small') +size3 = Size(size_description='Medium') +size4 = Size(size_description='Tall') +sizes = [size1, size2, size3, size4] + +# product table +product1 = Product(species='Boston Fern', price=12, stock=8, category_id=1, plant_type_id=5, size_id=1, plant_nickname="Wendy", general_info="Sword fern - Nephrolepis exaltata", care_tip1="Frequent watering", care_tip2="Most light conditions", care_tip3="Humidity", img_link1="images/boston_fern_bush.jpg", img_link2="images/boston_fern_single.jpg", img_link3="", tech_description="Dame Wendy Hall is a British computer scientist, well known for her development of the Microcosm hypermedia systenm in the mid-1980's, which was a forerunner ot the World Wide Web.") +product2 = Product(species='Aloe Vera', price=4, stock=10, category_id=1, plant_type_id=1, size_id=2, plant_nickname="Annie", general_info="Aloe barbadensis", care_tip1="Light watering", care_tip2="Bright light", care_tip3="Warmth", img_link1="images/aloe_vera.jpg", img_link2="images/aloe_vera_hand.jpg", img_link3="images/aloe_vera_pot.jpg", tech_description="Annie Easley was an American computer scientist, mathematician, and rocket scientist. She was a leading member of the team which developed software for the Centaur rocket stage, and was one of the first African-Americans to work at NASA.") +product3 = Product(species='Parlour Palm', price=8.99, stock=3, category_id=1, plant_type_id=4, size_id=2, plant_nickname="Hedy", general_info="Chamaedorea elegans; Neanthe bella palm", care_tip1="Frequent watering", care_tip2="Medium light", care_tip3="Humidity", img_link1="images/parlour_palm.jpg", img_link2="images/parlour_palm_close.jpg", img_link3="images/parlour_palm_zoomout.jpg", tech_description="Hedy LaMarr patented frequency-hopping technology in 1941 that became a precursor to the secure wi-fi, GPS and Bluetooth now used by billions of people around the world.") +product4 = Product(species='Anthurium', price=20, stock=5, category_id=1, plant_type_id=3, size_id=3, plant_nickname="Grace", general_info="Tail flower; Flamingo flower; Laceleaf; Anthurium Andraeanum", care_tip1="Light watering", care_tip2="Medium light", care_tip3="Humidity", img_link1="images/anthurium.jpg", img_link2="images/anthurium_pot.jpg", img_link3="images/anthurium_white.jpg'", tech_description="Grace Hopper was a well known pioneer of computer programming. She was the first to devise the theory of machine-independent programming languages, and the FLOW-MATIC programming language she created using this theory was later extended to create COBOL - an early high-level programming language still in use today.") +product5 = Product(species='Swiss Cheese Plant', price=85.5, stock=1, category_id=1, plant_type_id=4, size_id=4, plant_nickname="Ada", general_info="Monstera Deliciosa; Ceriman; Custard plant; Indian ivy; Fruit salad plant; Mexican breadfruit; Cheese plant", care_tip1="Light watering", care_tip2="Medium light", care_tip3="Humidity", img_link1="images/swiss_cheese_plant.jpg", img_link2="images/swiss_cheese_plant_close.jpg", img_link3="images/swiss_cheese_plant_small.jpg", tech_description="Ada Lovelace was an English mathematician and writer, chiefly known for her work on Charles Babbage's proposed mechanical general-purpose computer, the Analytical Engine. She was the first to recognise that the machine had applications beyond pure calculation, and to have published the first algorithm intended to be carried out by such a machine.") +product6 = Product(species='Sweet Orange Tree', price=65, stock=4, category_id=2, plant_type_id=3, size_id=4, plant_nickname="Roberta", general_info="Citrus Sinensis", care_tip1="Light watering", care_tip2="Bright light", care_tip3="Moist Soil", img_link1="images/sweet_orange_tree_1.jpg", img_link2="images/sweet_orange_tree_2.jpg", img_link3="images/sweet_orange_tree_3.jpg", tech_description="Roberta Williams is an American video game designer and writer, who co-founded Sierra On-Line, and became credited as the first graphic adventure game.") +product7 = Product(species='Climbing Rose', price=30, stock=3, category_id=2, plant_type_id=3, size_id=3, plant_nickname="Elizabeth", general_info="Rosa", care_tip1="Frequent watering", care_tip2="Partial sun", care_tip3="Moist Soil", img_link1="images/climbing_rose_1.jpg", img_link2="images/climbing_rose_2.jpg", img_link3="images/climbing_rose_3.jpg", tech_description="Elizabeth J Feinler is an information scientist who laid the foundations for how the internet is structured, including the Domain Name System (DNS).") +product8 = Product(species='Fatsia Japonica', price=55, stock=2, category_id=2, plant_type_id=5, size_id=3, plant_nickname="Valerie", general_info="Glossy-leaf paper plant; Fatsi; Paperplant; Japanese aralia", care_tip1="Medium watering", care_tip2="Partial sun", care_tip3="Moist Soil", img_link1="images/fatsia_japonica_berry.jpg", img_link2="images/fatsia_japonica_leaf.jpg", img_link3="", tech_description="Valerie Thomas is the inventor of the illusion transmitter. Valerie changed the way we consume content as she managed the development of NASA’s image-processing system for Landsat, the first satellite to send images from outer space. This is widely considered to be the basis for 3D technology.") +product9 = Product(species='Hydrangea Macrophylla', price=29.99, stock=5, category_id=2, plant_type_id=4, size_id=2, plant_nickname="Shirley", general_info="Mophead Hydrangea, French Hydrangea, Hortensia", care_tip1="Frequent watering", care_tip2="Partial sun", care_tip3="Moist Soil", img_link1="images/hydrangea_dusky_pink.jpg'", img_link2="images/hydrangea_hot_pink.jpg'", img_link3="images/hydrangea_white.jpg", tech_description="Dr Shirley Jackson was the first African American woman to earn a doctorate in nuclear physics at MIT. Her experiments led the way for numerous developments in the telecommunication space, including the invention of fibre-optic cables that link the world’s communication system.") +product10 = Product(species='Alstroemeria', price=27, stock=8, category_id=2, plant_type_id=4, size_id=1, plant_nickname="Victoria", general_info="Lily of the Incas", care_tip1="Light watering", care_tip2="Bright light", care_tip3="Warmth", img_link1="images/alstromeria_pink.jpg", img_link2="images/alstromeria_purple.jpg", img_link3="images/alstromeria_yellow.jpg", tech_description="Victoria Lloyd is a leading coding instructor, currently teaching women from across the UK how to code. She leads numerous cohorts of women looking to career switch, upskill and kickstart their coding journey, mentoring and advising on how to access the technology and software development fields.") +products = [product1, product2, product3, product4, product5, product6, product7, product8, product9, product10] + + +# OrderHeader linking to person only (as customer) +order1 = OrderHeader(person_id=1, order_date='2022-04-09', status_id=1, total_cost=54.00) # staff_id=1) +order2 = OrderHeader(person_id=2, order_date='2022-04-10', status_id=4, total_cost=26.97) # staff_id=2) +order3 = OrderHeader(person_id=3, order_date='2022-04-12', status_id=3, total_cost=197.97) # staff_id=3) +order4 = OrderHeader(person_id=4, order_date='2022-04-16', status_id=4, total_cost=20.00) # staff_id=4) +order5 = OrderHeader(person_id=1, order_date='2022-04-19', status_id=4, total_cost=195.00) #staff_id=1) +order6 = OrderHeader(person_id=4, order_date='2022-04-18', status_id=5, total_cost=105.00) #staff_id=1) +order7 = OrderHeader(person_id=4, order_date='2022-04-21', status_id=3, total_cost=172.48) #staff_id=1) +order8 = OrderHeader(person_id=4, order_date='2022-04-30', status_id=1, total_cost=12) #staff_id=1) +plant_orders = [order1, order2, order3, order4, order5, order6, order7, order8] + + +# orderLine +order_line1 = OrderLine(order_header_id=1, product_id=10, quantity=2, price_paid=54.00) +order_line2 = OrderLine(order_header_id=2, product_id=3, quantity=1, price_paid=26.97) +order_line3 = OrderLine(order_header_id=3, product_id=5, quantity=2, price_paid=171.00) +order_line4 = OrderLine(order_header_id=3, product_id=4, quantity=4, price_paid=80.00) +order_line5 = OrderLine(order_header_id=4, product_id=2, quantity=2, price_paid=8.00) +order_line6 = OrderLine(order_header_id=4, product_id=1, quantity=1, price_paid=12.00) +order_line7 = OrderLine(order_header_id=5, product_id=6, quantity=3, price_paid=195.00) +order_line8 = OrderLine(order_header_id=6, product_id=8, quantity=1, price_paid=55.00) +order_line9 = OrderLine(order_header_id=6, product_id=7, quantity=2, price_paid=60.00) +order_line10 = OrderLine(order_header_id=7, product_id=10, quantity=1, price_paid=27.00) +order_line11 = OrderLine(order_header_id=7, product_id=9, quantity=2, price_paid=59.98) +order_line12 = OrderLine(order_header_id=7, product_id=5, quantity=1, price_paid=85.50) +order_line13 = OrderLine(order_header_id=8, product_id=2, quantity=3, price_paid=12.00) +order_lines = [order_line1, order_line2, order_line3, order_line4, order_line5, order_line6, order_line7, order_line8, order_line9, order_line10, order_line11, order_line12, order_line13] + +db.session.add_all(blogs) +db.session.add_all(news) +db.session.add_all(person_types) +db.session.add_all(users) +db.session.add_all(addresses) +db.session.add_all(staff) +db.session.add_all(persons) +db.session.add_all(status) +db.session.add_all(categories) +db.session.add_all(plant_types) +db.session.add_all(sizes) +db.session.add_all(products) +db.session.add_all(plant_orders) +db.session.add_all(order_lines) + -db.session.add(testPerson1) -db.session.add(testPerson2) -# db.session.add(car1) -# db.session.add(car2) -# db.session.add(car3) -db.session.add_all(cars) -# db.session.add(car4) db.session.commit() + +# Victoria's Code: + +# testPerson1 = Person(first_name='Julie', last_name='Dooley') +# testPerson2 = Person(first_name='Victoria', last_name='Lloyd') +# +# car1 = Car(number_plate='JU21DOO', person_id=1, colour='Red', make="Ferrari", model='V12') +# car2 = Car(number_plate='JU20XXX', person_id=1, colour='Black', make="Mercedes-Benz", model='CLS') +# car3 = Car(number_plate='VL21LLO', person_id=2, colour='Grey', make="Ford", model='Focus') +# +# cars = [car1, car2, car3] +# # car4 = Car(number_plate='BART21', person_id=3) +# +# db.session.add(testPerson1) +# db.session.add(testPerson2) +# # db.session.add(car1) +# # db.session.add(car2) +# # db.session.add(car3) +# +# db.session.add_all(cars) +# # db.session.add(car4) +# db.session.commit() diff --git a/application/forms.py b/application/forms.py index 9013e03..fc53e8a 100644 --- a/application/forms.py +++ b/application/forms.py @@ -1,10 +1,153 @@ from flask_wtf import FlaskForm -from wtforms import StringField, SubmitField +from wtforms import StringField, SubmitField, PasswordField, BooleanField, DateField, IntegerField, SelectField +from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError +# need form to do email newsletter sign up +class EmailSignUpForm(FlaskForm): + email = StringField('Email') + submit = SubmitField('Sign Up') + + +def validate_username(form, field): + excluded_chars = " *?!'^+%&/()=}][{$#" + for char in form.username.data: + if char in excluded_chars: + raise ValidationError( + f'Character {char} is not allowed in username. Please do not use any of the following characters: {excluded_chars}') + +# new form needs to link to userlogin person and address tables for registering customers (is set in the route to set the +# persontype to '2' which is customer +class CustomerRegistrationForm(FlaskForm): + # userlogin elements + username = StringField('Username', validators=[DataRequired(), Length(min=2, max=30), validate_username]) + password = PasswordField('Password', validators=[DataRequired(), Length(min=6)]) + confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password', message="Passwords must match")]) + + # person elements + first_name = StringField('First Name', validators=[DataRequired(), Length(min=2, max=30)]) + last_name = StringField('Last Name', validators=[DataRequired(), Length(min=2, max=30)]) + email = StringField('Email', validators=[DataRequired(), Email(message='Please supply a valid email')]) + + # address elements + address_line_one = StringField('Address Line 1', validators=[DataRequired()]) + address_line_two = StringField('Address Line 2') + address_line_three = StringField('Address Line 3') + postcode = StringField('Postcode', validators=[DataRequired()]) + phone_number = StringField('Phone Number') + # submit + submit = SubmitField('Sign Up') + + + +class LoginForm(FlaskForm): + email = StringField('Email', validators=[DataRequired(), Email(message='Please supply a valid email')]) + password = PasswordField('Password', validators=[DataRequired()]) + remember = BooleanField('Remember Me') + submit = SubmitField('Login') + + +# as staff are now a type of person, this form gets a bit more complicated, needs to link to userlogin, address, +# person and staff info tables to be functional (can set persontype to '1' which is staff in the routes) +class StaffRegistrationForm(FlaskForm): + # userlogin elements + username = StringField('Username', validators=[DataRequired(), Length(min=2, max=30), validate_username]) + password = PasswordField('Password', validators=[DataRequired(), Length(min=6)]) + confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('confirm_password', + message="Passwords must match")]) + + # person elements + first_name = StringField('First Name', validators=[DataRequired(), Length(min=2, max=30)]) + last_name = StringField('Last Name', validators=[DataRequired(), Length(min=2, max=30)]) + email = StringField('Email', validators=[DataRequired(), Email(message='Please supply a valid email')]) + + # address elements + address_line_one = StringField('Address Line 1', validators=[DataRequired()]) + address_line_two = StringField('Address Line 2') + address_line_three = StringField('Address Line 3') + postcode = StringField('Postcode', validators=[DataRequired()]) + phone_number = StringField('Phone Number') + + # staff info elements + job_title = StringField('Job title', validators=[DataRequired()]) + date_of_birth = DateField('Date of birth', validators=[DataRequired()]) + # submit + submit = SubmitField('Register New Staff Member') + + +class PlantForm(FlaskForm): + # plant_name = StringField('Plant Name', validators=[DataRequired()]) + #removed plant_name field as not sure it was necessary, can add again if needed. Had to completely remove from html file as form would not work with it commented out, was still picking up on the website after submitting the form" + plant_species = StringField('Plant Species', validators=[DataRequired()]) + plant_type = SelectField('Type', choices=[('1', 'Cacti/Succulent'), ('2', 'Hanging'), ('3', 'Flowering'), ('4', 'Palms'), ('5', 'Ferns')], validators=[DataRequired()]) + plant_category = SelectField('Categories', choices=[('1', 'Indoor'), ('2', 'Outdoor')]) + plant_price = IntegerField('Plant Price', validators=[DataRequired()]) + plant_stock = IntegerField('Number Being Added To Stock', validators=[DataRequired()]) + plant_size = SelectField('Size', choices=[('1', 'Tiny'), ('2', 'Small'), ('3', 'Medium'), ('4', 'Tall')], validators=[DataRequired()]) + plant_nickname = StringField('Plant Nickname', validators=[DataRequired()]) + plant_info = StringField('General Plant Info', validators=[DataRequired()]) + care_tip_1 = StringField('First Care Tip', validators=[DataRequired()]) + care_tip_2 = StringField('Second Care Tip') + care_tip_3 = StringField('Third Care Tip') + image_1 = StringField('Image Link', validators=[DataRequired()]) + image_2 = StringField('Image Link') + image_3 = StringField('Image Link') + tech_description = StringField('Women in tech description', validators=[DataRequired()]) + submit = SubmitField('Register Plant') + + +# add a new blog post +class NewBlogPostForm(FlaskForm): + title = StringField('Title', validators=[DataRequired()]) + author = StringField('Author', validators=[DataRequired()]) + post_content = StringField('Post Content', validators=[DataRequired()]) + + submit = SubmitField('Add post') + +# delete blog post +class DeleteBlogPostForm(FlaskForm): + id = IntegerField('ID of the post you want to delete', validators=[DataRequired()]) + + submit = SubmitField('Delete post') + +# log in form +class LogInForm(FlaskForm): + username = StringField('Username', validators=[DataRequired()]) + password = PasswordField('Password', validators=[DataRequired()]) + type = SelectField('Type', choices=[('1', 'Staff'), ('2', 'Customer')]) + + submit = SubmitField('Log in') + +# add to cart +class AddToCartForm(FlaskForm): + product = SelectField('Species', choices=[(1, 'Boston Fern'), (2, 'Aloe Vera'), (3, 'Parlour Palm')]) + # product = SelectField('Species', choices=['Boston Fern', 'Aloe Vera', 'Parlour Palm']) + quantity = IntegerField('Quantity', validators=[DataRequired()]) + # price = + submit = SubmitField('Add to cart') + +# create a search form +class SearchForm(FlaskForm): + searched = StringField('Searched', validators=[DataRequired()]) + submit = SubmitField('Submit') + + +class OrderForm(FlaskForm): + # basically as the fields we need to make a new db record are already in the cart values or can be autopopulated, + # so think you would just use this form as the confirmation button + # submit + submit = SubmitField('Place Order') + +class UpdateEmailForm(FlaskForm): + new_email = StringField('New email address', validators=[DataRequired()]) + # submit + submit = SubmitField('Update Email') + +# Victoria's code class BasicForm(FlaskForm): first_name = StringField('First Name') last_name = StringField('Last Name') submit = SubmitField('Add Name') + diff --git a/application/models.py b/application/models.py index b72ea0f..af81b7f 100644 --- a/application/models.py +++ b/application/models.py @@ -1,18 +1,162 @@ -from application import db # import the sqlalchemy object (db) created for our app +from application import db # import the sqlalchemy object (db) created for our app +# Blog posts +class BlogPosts(db.Model): + id = db.Column(db.Integer, primary_key=True) + author = db.Column(db.String(50), nullable=False) + date_posted = db.Column(db.Date, nullable=False) + title = db.Column(db.String(50), nullable=False) + post_content = db.Column(db.String(1000), nullable=False) + + + +# Newsletter signup +class Newsletter(db.Model): + id = db.Column(db.Integer, primary_key=True) + newsletter_email = db.Column(db.String(120), nullable=False) + +# PersonType linking to Person +class PersonType(db.Model): + id = db.Column(db.Integer, primary_key=True) + person_type_description = db.Column(db.String(50), nullable=False) + # not a field in the table, but PersonType table links back to Person(can use to set permissions + # in later iteration) + person_type = db.relationship('Person', backref='person_type') + + +# UserLogin linking to Person +class UserLogin(db.Model): + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(50), nullable=False) + password = db.Column(db.String(50), nullable=False) + # not field in table but relationship between userlogin and person + user_login = db.relationship('Person', backref='user_login') + +# address linking to person +class Address(db.Model): + id = db.Column(db.Integer, primary_key=True) + address_line_one = db.Column(db.String(50), nullable=False) + address_line_two = db.Column(db.String(50), nullable=True) + address_line_three = db.Column(db.String(50), nullable=True) + address_line_four = db.Column(db.String(50), nullable=True) + postcode = db.Column(db.String(50), nullable=False) + # relationship between address and customer table - several people may have the same address + address = db.relationship('Person', backref='address') + + +# Staff Info - allows us to record extra info about staff, but also gives them staff ID number to use to assign +# to orders for packing etc +class StaffInfo(db.Model): + id = db.Column(db.Integer, primary_key=True) + job_title = db.Column(db.String(50), nullable=False) + date_of_birth = db.Column(db.Date, nullable=False) + staff_info = db.relationship('Person', backref='staff_info') + + + +# Person linking to address userlogin and orderheader class Person(db.Model): id = db.Column(db.Integer, primary_key=True) first_name = db.Column(db.String(30), nullable=False) last_name = db.Column(db.String(30), nullable=False) - cars = db.relationship('Car', backref='person') + email = db.Column(db.String(120), nullable=False) + # address_id is the Foreign Key linking to the Address table + address_id = db.Column(db.Integer, db.ForeignKey('address.id'), nullable=False) + phone_number = db.Column(db.String(30), nullable=False) + # user_login_id is linking back for username and password purposes + user_login_id = db.Column(db.Integer, db.ForeignKey('user_login.id'), nullable=False) + person_type_id = db.Column(db.Integer, db.ForeignKey('person_type.id'), nullable=False) + staff_info_id = db.Column(db.Integer, db.ForeignKey('staff_info.id'), nullable=True) + # not a field in the table, but OrderHeader table links back to PersonID + person_id = db.relationship('OrderHeader', backref='person') -class Car(db.Model): +class OrderStatus(db.Model): + id = db.Column(db.Integer, primary_key=True) + status_description = db.Column(db.String(50), nullable=False) + # not a field in the table, but OrderStatus table links back to OrderHeader + order_status = db.relationship('OrderHeader', backref='order_status') + + +class Category(db.Model): + id = db.Column(db.Integer, primary_key=True) + category_description = db.Column(db.String(50), nullable=False) + # not a field in the table, but Category table links back to Product + category = db.relationship('Product', backref='category') + + +class PlantType(db.Model): + id = db.Column(db.Integer, primary_key=True) + plant_type_description = db.Column(db.String(50), nullable=False) + # not a field in the table, but PlantType table links back to Product + plant_type = db.relationship('Product', backref='plant_type') + + +class Size(db.Model): + id = db.Column(db.Integer, primary_key=True) + size_description = db.Column(db.String(50), nullable=False) + # not a field in the table, but Size table links back to Product + size = db.relationship('Product', backref='size') + + +class Product(db.Model): + id = db.Column(db.Integer, primary_key=True) + species = db.Column(db.String(50), nullable=False) + # is this the right data type to store number to 2 decimal places? + price = db.Column(db.Integer, nullable=False) + stock = db.Column(db.Integer, nullable=False) + category_id = db.Column(db.Integer, db.ForeignKey('category.id'), nullable=False) + plant_type_id = db.Column(db.Integer, db.ForeignKey('plant_type.id'), nullable=False) + size_id = db.Column(db.Integer, db.ForeignKey('size.id'), nullable=False) + plant_nickname = db.Column(db.String(50), nullable=False) + general_info = db.Column(db.String(200), nullable=False) + care_tip1 = db.Column(db.String(100), nullable=False) + care_tip2 = db.Column(db.String(100), nullable=True) + care_tip3 = db.Column(db.String(100), nullable=True) + img_link1 = db.Column(db.String(200), nullable=False) + img_link2 = db.Column(db.String(200), nullable=True) + img_link3 = db.Column(db.String(200), nullable=True) + tech_description = db.Column(db.String(400), nullable=False) + # not a field in the table, but OrderLine table links back to Product + product = db.relationship('OrderLine', backref='product') + +class OrderHeader(db.Model): id = db.Column(db.Integer, primary_key=True) - number_plate = db.Column(db.String(7), nullable=False) - colour = db.Column(db.String(10), nullable=False) - make = db.Column(db.String(20), nullable=False) - model = db.Column(db.String(20), nullable=False) person_id = db.Column(db.Integer, db.ForeignKey('person.id'), nullable=False) + # not totally sure how we do dates, check this + order_date = db.Column(db.Date, nullable=False) + status_id = db.Column(db.Integer, db.ForeignKey('order_status.id'), nullable=False) + # also what is best data type for price data? + total_cost = db.Column(db.Integer) + # staff_id = db.Column(db.Integer, db.ForeignKey('StaffInfo.id'), nullable=False) + # staff_id = db.Column(db.Integer, db.ForeignKey('person.staff_info_id'), nullable=False) + # not a field in the table, but OrderLine table links back to OrderHeader + order_header = db.relationship('OrderLine', backref='order_header') + + +class OrderLine(db.Model): + id = db.Column(db.Integer, primary_key=True) + order_header_id = db.Column(db.Integer, db.ForeignKey('order_header.id'), nullable=False) + product_id = db.Column(db.Integer, db.ForeignKey('product.id'), nullable=False) + quantity = db.Column(db.Integer, nullable=False) + # also what is best data type for price data? + price_paid = db.Column(db.Integer) + + +# Victoria's code: +# class Person(db.Model): +# id = db.Column(db.Integer, primary_key=True) +# first_name = db.Column(db.String(30), nullable=False) +# last_name = db.Column(db.String(30), nullable=False) +# cars = db.relationship('Car', backref='person') +# +# +# class Car(db.Model): +# id = db.Column(db.Integer, primary_key=True) +# number_plate = db.Column(db.String(7), nullable=False) +# colour = db.Column(db.String(10), nullable=False) +# make = db.Column(db.String(20), nullable=False) +# model = db.Column(db.String(20), nullable=False) +# person_id = db.Column(db.Integer, db.ForeignKey('person.id'), nullable=False) diff --git a/application/routes.py b/application/routes.py index 1d68b54..f67f1c1 100644 --- a/application/routes.py +++ b/application/routes.py @@ -1,117 +1,1023 @@ -from flask import render_template, request +from flask import render_template, request, flash, redirect, url_for, session from application import app, db -from application.forms import BasicForm -from application.models import Person, Car +from application.forms import EmailSignUpForm, CustomerRegistrationForm, StaffRegistrationForm, PlantForm,\ + NewBlogPostForm, LogInForm, AddToCartForm, DeleteBlogPostForm, SearchForm, OrderForm, UpdateEmailForm +from application.models import Person, Address, Newsletter, UserLogin, StaffInfo, Product, BlogPosts,\ + OrderHeader, OrderLine, OrderStatus, Category, PlantType, Size +from datetime import date + +# newsletter sign up form for homepage @app.route('/', methods=['GET', 'POST']) @app.route('/home', methods=['GET', 'POST']) + +def email_signup_form(): + error = "" + form = EmailSignUpForm() + + if request.method == 'POST': + email = form.email.data + if len(email) == 0: + error = "Please supply email address" + else: + news = Newsletter(newsletter_email=email) + db.session.add(news) + db.session.commit() + flash(f'Success! {form.email.data} will now get our lovely email newsletter', 'success') + return render_template('home.html', form=form, message=error, title='home') + return render_template('home.html', form=form, message=error, title='home') + + +# LINKS TO PLANT HTML PAGES + +@app.route('/about', methods=['GET']) +def about(): + return render_template('about.html', title='About') + + +@app.route('/contact_us', methods=['GET']) +def contact(): + return render_template('contact_us.html', title='Contact Us') + + +# @app.route('/shop', methods=['GET']) +# def shop(): +# return render_template('shop.html', title='Shop') + + +@app.route('/plant1', methods=['GET']) +def plant1(): + return render_template('plant1.html', title='Plant 1') + + +@app.route('/plant2', methods=['GET']) +def plant2(): + return render_template('plant2.html', title='Plant 2') + + +@app.route('/plant3', methods=['GET']) +def plant3(): + return render_template('plant3.html', title='Plant 3') + + +@app.route('/plant4', methods=['GET']) +def plant4(): + return render_template('plant4.html', title='Plant 4') + + +@app.route('/plant5', methods=['GET']) +def plant5(): + return render_template('plant5.html', title='Plant 5') + + +@app.route('/plant6', methods=['GET']) +def plant6(): + return render_template('plant6.html', title='Plant 6') + + +@app.route('/plant7', methods=['GET']) +def plant7(): + return render_template('plant7.html', title='Plant 7') + + +@app.route('/plant8', methods=['GET']) +def plant8(): + return render_template('plant8.html', title='Plant 8') + + +@app.route('/plant9', methods=['GET']) +def plant9(): + return render_template('plant9.html', title='Plant 9') + + +@app.route('/plant10', methods=['GET']) +def plant10(): + return render_template('plant10.html', title='Plant 10') + + +# CUSTOMER RELATED ROUTES: + +# REGISTERING A NEW CUSTOMER: + + +@app.route('/register', methods=['GET', 'POST']) def register(): error = "" - form = BasicForm() + form = CustomerRegistrationForm() + + if form.validate_on_submit(): + flash(f'Account created for {form.username.data}!', 'success') + else: + return render_template('register.html', form=form) if request.method == 'POST': + username = form.username.data + password = form.password.data first_name = form.first_name.data last_name = form.last_name.data + email = form.email.data + address_line_one = form.address_line_one.data + address_line_two = form.address_line_two.data + address_line_three = form.address_line_three.data + postcode = form.postcode.data + phone_number = form.phone_number.data - if len(first_name) == 0 or len(last_name) == 0: - error = "Please supply both first and last name" + if request.method == 'POST': + username = form.username.data + password = form.password.data + first_name = form.first_name.data + last_name = form.last_name.data + email = form.email.data + address_line_one = form.address_line_one.data + address_line_two = form.address_line_two.data + address_line_three = form.address_line_three.data + postcode = form.postcode.data + phone_number = form.phone_number.data + + if len(first_name) == 0 \ + or len(last_name) == 0 \ + or len(email) == 0\ + or len(address_line_one) == 0\ + or len(postcode) == 0\ + or len(password) < 4\ + or len(username) == 0: + error = "Please complete each section of this form" else: - person = Person(first_name=first_name, last_name=last_name) + user_login = UserLogin(username=username, + password=password) + address = Address(address_line_one=address_line_one, + address_line_two=address_line_two, + address_line_three=address_line_three, + postcode=postcode) + person = Person(first_name=first_name, + last_name=last_name, + email=email, + address=address, + phone_number=phone_number, + person_type_id=2, + user_login=user_login) + + db.session.add(user_login) + db.session.add(address) db.session.add(person) db.session.commit() - return 'Thank you!' + return render_template('home.html', title='Home', message=error, form=form) + return render_template('register.html', title='Register', message=error, form=form) + + +# ACCESSING A LIST OF CUSTOMERS +# This is functional + + +@app.route('/customer_list', methods=['GET']) +def show_customers(): + error = "" + customer = Person.query.filter_by(person_type_id=2) + # if len(customer) == 0: + # error = "There are no people to display" + # print(customer) + return render_template('customer_list.html', customer=customer, message=error) + + +# STAFF RELATED ROUTES + +# REGISTERING A NEW MEMBER OF STAFF: + + +@app.route('/register_staff', methods=['GET', 'POST']) +def register_staff(): + error = "" + form = StaffRegistrationForm() + + if form.validate_on_submit(): + flash(f' Staff account created for {form.username.data}!', 'success') + else: + return render_template('register_staff.html', form=form) + + if request.method == 'POST': + username = form.username.data + password = form.password.data + first_name = form.first_name.data + last_name = form.last_name.data + email = form.email.data + address_line_one = form.address_line_one.data + address_line_two = form.address_line_two.data + address_line_three = form.address_line_three.data + postcode = form.postcode.data + phone_number = form.phone_number.data + job_title = form.job_title.data + date_of_birth = form.date_of_birth.data + + # if messages left in for all form routes because may need to raise error here for validations that aren't currently showing + if len(first_name) == 0 \ + or len(last_name) == 0 \ + or len(email) == 0\ + or len(address_line_one) == 0\ + or len(postcode) == 0\ + or len(password) < 4\ + or len(username) == 0: + error = "Please complete each section of this form" + else: + user_login = UserLogin(username=username, + password=password) + address = Address(address_line_one=address_line_one, + address_line_two=address_line_two, + address_line_three=address_line_three, + postcode=postcode) + staff_info = StaffInfo(job_title=job_title, + date_of_birth=date_of_birth) + person = Person(first_name=first_name, + last_name=last_name, + email=email, + address=address, + phone_number=phone_number, + person_type_id=1, + user_login=user_login, + staff_info=staff_info) + db.session.add(user_login) + db.session.add(address) + db.session.add(staff_info) + db.session.add(person) + db.session.commit() + return render_template('home.html', title='Home', message=error, form=form) + return render_template('register_staff.html', title='Register New Staff', message=error, form=form) + + +# ACCESSING A LIST OF CURRENT STAFF + +@app.route('/staff_list', methods=['GET']) +def show_staff(): + error = "" + staff = Person.query.filter_by(person_type_id=1) + # if len(customer) == 0: + # error = "There are no people to display" + # print(customer) + return render_template('staff_list.html', staff=staff, message=error) + + +# DELETE STAFF ACCOUNTS - currently provides error message 'method not allowed' +# @app.route('/staff/', methods=['DELETE']) +# def delete_staff(staff_id): +# error = "" +# staff = Staff.query.get(staff_id) +# db.session.delete(staff) +# db.session.commit() +# staff = Staff.query.all() +# if not staff: +# error = "There is no staff with ID: " + str(staff_id) +# print(staff) +# return render_template('staff_deletion.html', staff=staff, message=error, title="Delete Staff") + +# REGISTERING A NEW PLANT: + + +@app.route('/plant_form', methods=['GET', 'POST']) +def plant_form(): + error = "" + form = PlantForm() + + if form.validate_on_submit(): + flash(f' Plant added!', 'success') + + if request.method == 'POST': + # plant_name = form.plant_name.data + plant_category = form.plant_category.data + plant_species = form.plant_species.data + plant_price = form.plant_price.data + plant_stock = form.plant_stock.data + plant_type = form.plant_type.data + plant_size = form.plant_size.data + + if len(plant_category) == 0 \ + or plant_species == 0\ + or plant_price == 0\ + or plant_stock == 0: + error = "Please complete the fields" + else: + product = Product(species=plant_species, + price=plant_price, + stock=plant_stock, + category_id=plant_category, + plant_type_id=plant_type, + size_id=plant_size) + db.session.add(product) + db.session.commit() + return render_template('plant_form.html', title='Register a Plant', message=error, form=form) + return render_template('plant_form.html', title='Register a Plant', message=error, form=form) + +# ACCESSING A LIST OF PLANTS: +# to do +# DELETING PLANTS WE NO LONGER STOCK: +# to do + + + +@app.route('/plant_care', methods=['GET']) +def plant_care(): + posts = BlogPosts.query.order_by(BlogPosts.date_posted.desc()).all() + return render_template('plant_care.html', title='Plant Care', posts=posts) + +@app.route('/addpost', methods=['GET', 'POST']) +def addpost(): + error = "" + form = NewBlogPostForm() + + if form.validate_on_submit(): + flash(f' New Blog Post created called {form.title.data}!', 'success') + + if request.method == 'POST': + title = form.title.data + author = form.author.data + post_content = form.post_content.data + if len(title) == 0\ + or len(author) == 0\ + or len(post_content) == 0: + error = "Please complete the fields" + else: + post = BlogPosts(title=title, author=author, post_content=post_content, date_posted=date.today()) + db.session.add(post) + db.session.commit() + posts = BlogPosts.query.order_by(BlogPosts.date_posted.desc()).all() + return render_template('plant_care.html', title='Plant Care', posts=posts) + + return render_template('addpost.html', message= error, form=form) + +# display specific blog post +@app.route('/post/') +def post(post_id): + post = BlogPosts.query.filter_by(id=post_id).one() + + return render_template('post.html', post=post) + +# delete blog post - functional in postman, trying to make work on the website +# something weird happening here, is putting csrf token in browser when you hit the delete button +@app.route('/delete_blogpost', methods=['GET','DELETE']) +# @app.route('/delete_blogpost/', methods=['GET','DELETE']) +def delete_blogpost(): + error = "" + form = DeleteBlogPostForm() + + # if request.method == 'DELETE': + # id_to_delete = form.id.data + # post = BlogPosts.query.get(id=id_to_delete) + # print(post) + # db.session.delete(post) + # db.session.commit() + # + # if not post: + # error = "There is no blog post with ID: " + str(form.id.data) + + # else: + # + # posts = BlogPosts.query.order_by(BlogPosts.date_posted.desc()).all() + # return render_template('plant_care.html', title='Plant Care', message= error, posts=posts, form=form) + + return render_template('delete_blogpost.html', title='Delete a blogpost', message= error, form=form) + +# dont think we need this anymore +# @app.route('/delete_blogpost_info', methods=['GET']) +# def delete_blogpost_info(): +# return render_template('delete_blogpost.html', title='Delete Blog post') + + +# session variables - login + +@app.route('/login', methods=['GET', 'POST']) +@app.route('/log_in', methods=['GET', 'POST']) +def login(): + form = LogInForm() + error = "" + # login_redirect = url_for('login') + if request.method == 'POST': + # pop previous session in case someone was already logged in + session.pop('logged_in_username', default=None) + session.pop('typesession', default=None) + session.pop('logged_in', default=None) + session.pop('id_number', default=None) + session.pop('cart', default=None) + + # if form.validate_on_submit(): + + # # taking the username and password from the form so that we can compare to the db + form_username = request.form['username'] + form_password = request.form['password'] + + db_username_password = UserLogin.query.filter_by(username=form_username, password=form_password).all() + for user_id in db_username_password: + user_id_for_session_variable = user_id.id + + # setting initial value of password_check to false: + password_check = False + + if db_username_password != []: + password_check = True + else: + password_check = False + + if password_check == True: + + # if validation has passed, save the username to the session object + session['logged_in_username'] = request.form['username'] + session['logged_in'] = True + session['id_number'] = user_id_for_session_variable + + # also need to check if they are a customer or staff, so need a another session variable + # some sort of if statement needed here to check db and then: + + # this query gives you all the staff id numbers, can we then filter this based on username/id? + # user_and_persontype = db.session.query(UserLogin, Person, StaffInfo).select_from(UserLogin).join(Person).join(StaffInfo).all() + # print(user_and_persontype) - return render_template('home.html', form=form, message=error) + # assigning type log in based on db not the dropdown: -@app.route('/people', methods=['GET']) -def show_people(): + login_type = Person.query.filter_by(id=user_id_for_session_variable).all() + for person in login_type: + login_type_staff = person.person_type_id + + # print(login_type_staff) + + if login_type_staff == 1: + # if person_type = 1 then: + session['typesession'] = 'staff' + else: + session['typesession'] = 'customer' + + # not currently checking db, but will take the form input instead as a starting point: + # if request.form['type'] == '1': + # # if person_type = 1 then: + # session['typesession'] = 'staff' + # else: + # session['typesession'] = 'customer' + + # will then return different nav/functionality depending on which type of log in it is - this works + + # will show shop page plus session variable specific text + return redirect(url_for('shop')) + + else: + flash(f' Login failed, please try again', 'danger') + # will just show basic shop page, no session data + return redirect(url_for('shop')) + # will display welcome message/session data and also navigation will change + return redirect(url_for('shop')) + + # if validation fails, return to log in page and flash message that it has failed + # return redirect(url_for('login')) + + return render_template('login.html', message= error, form=form) + +# session variables - log out + +@app.route('/log_out') +@app.route('/logout') +def delete_session(): error = "" - people = Person.query.all() - if len(people) == 0: - error = "There are no people to display" - print(people) - return render_template('people.html', people=people, message=error) + form = EmailSignUpForm() + # Clear the username stored in the session object + session.pop('logged_in_username', default=None) + session.pop('typesession', default=None) + session.pop('logged_in', default=None) + session.pop('id_number', default=None) + session.pop('cart', default=None) + + flash(f' You have logged out!', 'success') + return render_template('home.html', title='Home', form=form, message=error,) + +# session variables - shopping cart + +@app.route('/add_to_cart', methods=['POST']) +def add_to_cart(): -@app.route('/cars', methods=['GET']) -def show_cars(): error = "" - cars = Car.query.all() - if len(cars) == 0: - error = "There are no cars to display" - print(cars) - return render_template('cars.html', cars=cars, message=error, title="Car") + form = AddToCartForm() + + # error message if user tries to press add to cart when not logged in + if 'logged_in' not in session: + flash(' Please Login to make a purchase', 'danger') + return redirect(url_for('login')) + return render_template('login.html', title='Home', form=form, message=error) + # return render_template('add_to_cart.html', form=form, message=error, title='home') -@app.route('/people/', methods=['GET']) -def show_person(person_id): + headings = ('Image', 'Plant Name', 'Species', 'Price', 'Quantity', 'Sub-Total') + + # if request.method == 'POST': + + plant_id = int(request.referrer.split('/')[4]) + plant = Product.query.filter_by(id=plant_id).one() + # product = form.product.data + # quantity = form.quantity.data + + # price = [Product.query.filter_by(product).first()] + # price = form.price.data + # attributes = Product.query.filter_by(id=product).all() + + # + # productAttributes = [] + + # what if we nested dictionaries not lists? + # productAttributes = {} + attributeObject = {} + # for attribute in plant: + + attributeObject['id'] = plant.id + attributeObject['species'] = plant.species + attributeObject['price'] = plant.price + attributeObject['plant_nickname'] = plant.plant_nickname + attributeObject['quantity'] = form.quantity.data + attributeObject['sub_total'] = (plant.price * form.quantity.data) + if 'cart' in session: + # session['cart'].append(attributeObject) + # below for loop merges duplicates when item added to the cart twice + plantInCart = False + for idx, cart_item in enumerate(session['cart']): + if plant.id == cart_item['id']: + session['cart'][idx]['quantity'] += form.quantity.data + session['cart'][idx]['sub_total'] += plant.price * form.quantity.data + plantInCart = True + if not plantInCart: + session['cart'].append(attributeObject) + session.modified = True + else: + session['cart'] = [attributeObject] + + return render_template('cart_success.html', title='Cart', form=form, message=error, attributeObject=attributeObject, cart_contents=session['cart'], headings=headings) + # return render_template('cart.html', title='Cart', form=form, message=error, cart_contents=session['cart'], headings=headings) + +# view cart (currently very basic!) +@app.route('/cart', methods=['GET', 'POST']) +def view_cart(): error = "" - # use filter_by for any column - # person = Person.query.filter_by(id=person_id).first() - # use get for the PK - person = Person.query.get(person_id) + # form was set to AddToCart() but trying to get ordering working + form = OrderForm() + if 'cart' in session: + cart_contents = session['cart'] + else: + cart_contents = [] - # simpsons = Person.query.filter_by(last_name="simpson").all() + headings = ('Image', 'Plant Name', 'Species', 'Price', 'Quantity', 'Sub-Total') - # to sort - # simpsons = Person.query.filter_by(last_name="simpson").order_by(Person.first_name).all() - # descending sort - # simpsons = Person.query.filter_by(last_name="simpson").order_by(Person.first_name.desc()).all() - # limit to top 2 simpsons - simpsons = Person.query.filter_by(last_name="simpson").order_by(Person.first_name).limit(2).all() - if not person: - error = "There is no person with ID: " + str(person_id) - print(person) - return render_template('person.html', person=person, message=error, title="Person", family=simpsons) + return render_template('cart.html', title='Cart', form=form, message=error, cart_contents=cart_contents, headings=headings) + # return render_template('add_to_cart.html', form=form, message=error, title='home') -@app.route('/people/', methods=['PUT']) -def update_person(person_id): +# empty cart (but will stay logged in) +@app.route('/clear_cart') +def clear_cart(): error = "" - person = Person.query.get(person_id) - person.last_name = "Flanders" - db.session.commit() - if not person: - error = "There is no person with ID: " + str(person_id) - print(person) - return render_template('person.html', person=person, message=error, title="Person", family=[]) + form = EmailSignUpForm() + # Clear the shopping cart in the session object + session.pop('cart', default=None) + + flash(f' You have emptied your cart!', 'success') + return render_template('home.html', title='Home', form=form, message=error,) + +# to get dynamic pricing in the drop down on the add to cart form for one item - in progress (abandoned) +# @app.route('/price/') +# def get_price(product_id): +# attributes = Product.query.filter_by(id=product_id).all() +# +# priceList = [] +# +# for attribute in attributes: +# attributeObject ={} +# attributeObject['id'] = attribute.id +# attributeObject['species'] = attribute.species +# attributeObject['price'] = attribute.price +# attributeObject['plant_nickname'] = attribute.plant_nickname +# priceList.append(attributeObject) +# +# # return ({'price_value': priceList}) +# return render_template('cart.html', title='Cart', priceList=priceList) + +# error handling - custom 404 page +@app.errorhandler(404) +def page_not_found(error): + return render_template('page_not_found.html'), 404 -@app.route('/people//', methods=['PUT']) -def update_person_with_name(person_id, new_last_name): +# order history - not quite working yet +@app.route('/customer_order_history', methods=['GET']) +def customer_order_history(): error = "" - person = Person.query.get(person_id) - person.last_name = new_last_name - db.session.commit() - if not person: - error = "There is no person with ID: " + str(person_id) - print(person) - return render_template('person.html', person=person, message=error, title="Updated Person", family=[]) + person_id = session['id_number'] + headings = ('Order ID number', 'Order Status', 'Date of Order', 'Species', 'Quantity', 'Total Price') + customer_order_history = db.session.query(OrderHeader, OrderStatus, OrderLine, Product).select_from(OrderHeader). \ + join(OrderStatus).join(OrderLine).join(Product).filter(OrderHeader.person_id == person_id).all() + + return render_template('order_history.html', title='Order History', customer_order_history=customer_order_history, message=error, headings=headings) + + +# Pass Stuff to Nav +@app.context_processor +def layout(): + form = SearchForm() + return dict(form=form) -@app.route('/people/', methods=['DELETE']) -def delete_person(person_id): +# create search function +@app.route('/search', methods=["POST"]) +def search(): + form = SearchForm() + posts = BlogPosts.query + if form.validate_on_submit(): + + # get data from submitted form + post.searched = form.searched.data + # Query the database + posts = posts.filter(BlogPosts.post_content.like('%' + post.searched + '%')) + posts = posts.order_by(BlogPosts.title).all() + + return render_template("search.html", form=form, searched=post.searched, posts=posts) + + +@app.route('/plant/') +def plant(plant_id): + + # form = AddToCartForm() + + plant = Product.query.filter_by(id=plant_id).one() + + return render_template('plant.html', title="Plant", plant=plant) + + +# STAFF ACCESS QUERIES + +# QUERY - in progress: staff and corresponding job titles +# Gives list of staff members and their job titles +@app.route('/staff_jobs', methods=['GET']) +def staff_jobs(): + error = "" + staff_and_jobs = db.session.query(StaffInfo, Person).join(Person).all() + headings = ('Job Title', 'First Name', 'Last Name', 'Email') + + # for job, staff in staff_and_jobs: + # print(job.job_title, staff.first_name, staff.last_name) + return render_template('staff_jobs.html', staff_and_jobs=staff_and_jobs, message=error, headings=headings) + + +# QUERY: customers and their orders +# Gives list of customer names, their order id and order date, the products ordered and the quantity +@app.route('/customer_orders', methods=['GET']) +def show_customer_orders(): error = "" - person = Person.query.get(person_id) - db.session.delete(person) - db.session.commit() - people = Person.query.all() - if not person: - error = "There is no person with ID: " + str(person_id) - # print(person) - return render_template('people.html', people=people, message=error, title="People") + headings = ('Order ID number', 'Customer First Name', 'Customer Last Name', 'Date of Order', 'Order Status', 'Species', 'Quantity') + customer_orders = db.session.query(Person, OrderHeader, OrderStatus, OrderLine, Product).select_from(Person).join( + OrderHeader).join(OrderStatus).join(OrderLine).join(Product).all() + return render_template('customer_orders.html', customer_orders=customer_orders, message=error, headings=headings) -@app.route('/personandcars/', methods=['GET']) -def people_and_cars(person_id): +# QUERY: Outstanding orders +@app.route('/outstanding_orders', methods=['GET']) +def show_outstanding_orders(): error = "" - person = Person.query.get(person_id) - # cars= person.cars - if not person: - error = "There is no person with ID: " + str(person_id) - print(person) - # print(person_and_carinfo) - return render_template('person_and_cars.html', person=person, message=error, title="Person and Car Info") + headings = ('Order ID', 'Order Date', 'Order Status', 'Species', 'Quantity') + outstanding_orders = db.session.query(OrderHeader, OrderStatus, OrderLine, Product).select_from(OrderHeader). \ + join(OrderStatus).join(OrderLine).join(Product).filter(OrderStatus.id == 1).all() + return render_template('outstanding_orders.html', outstanding_orders=outstanding_orders, message=error, headings=headings) + +# current stock list for staff query +@app.route('/stock_list', methods=['GET']) +def stock_list(): + headings = ('Species', 'Environment', 'Size', 'Plant Type', 'Price', 'In Stock') + plant_shop_plant = db.session.query(Product, Category, PlantType, Size).select_from(Product). \ + join(Category).join(PlantType).join(Size).order_by(Product.species.asc()).all() + return render_template('stock_list.html', title='Stock List', plant_shop_plant=plant_shop_plant, headings=headings) + + + +# CUSTOMER ACCESS QUERIES + +# PLANT SHOP PAGE - IN PROGRESS + +# MAIN SHOP PAGE +@app.route('/shop', methods=['GET']) +def shop(): + plant_shop_plant = db.session.query(Product, Category, PlantType, Size).select_from(Product). \ + join(Category).join(PlantType).join(Size).all() + return render_template('shop.html', title='Plant Shop', plant_shop_plant=plant_shop_plant) + +@app.route('/plant/') +def product_store(product_id): + plant = Product.query.filter_by(id=product_id).one() + + return render_template('plant.html', plant=plant) + + + +# QUERY: Indoor plants +@app.route('/indoor_plants', methods=['GET']) +def show_indoor_plants(): + error = "" + display_indoor_plants = db.session.query(Product, Category, PlantType, Size).select_from(Product). \ + join(Category).join(PlantType).join(Size).filter(Category.id == 1).order_by(Product.price.desc()).all() + return render_template('shop.html', display_indoor_plants=display_indoor_plants, message=error) + + +# QUERY: Outdoor plants +@app.route('/outdoor_plants', methods=['GET']) +def show_outdoor_plants(): + error = "" + display_outdoor_plants = db.session.query(Product, Category, PlantType, Size).select_from(Product). \ + join(Category).join(PlantType).join(Size).filter(Category.id == 2).order_by(Product.price.desc()).all() + return render_template('shop.html', display_outdoor_plants=display_outdoor_plants, message=error) + + +# QUERY: filter by height - tiny +@app.route('/tiny_plants', methods=['GET']) +def show_tiny_plants(): + error = "" + display_tiny_plants = db.session.query(Product, Category, PlantType, Size).select_from(Product). \ + join(Category).join(PlantType).join(Size).filter(Size.id == 1).order_by(Product.price.desc()).all() + return render_template('shop.html', display_tiny_plants=display_tiny_plants, message=error) + +# QUERY: filter by height - small +@app.route('/small_plants', methods=['GET']) +def show_small_plants(): + error = "" + display_small_plants = db.session.query(Product, Category, PlantType, Size).select_from(Product). \ + join(Category).join(PlantType).join(Size).filter(Size.id == 2).order_by(Product.price.desc()).all() + return render_template('shop.html', display_small_plants=display_small_plants, message=error) + +# QUERY: filter by height - medium +@app.route('/medium_plants', methods=['GET']) +def show_medium_plants(): + error = "" + display_medium_plants = db.session.query(Product, Category, PlantType, Size).select_from(Product). \ + join(Category).join(PlantType).join(Size).filter(Size.id == 3).order_by(Product.price.desc()).all() + return render_template('shop.html', display_medium_plants=display_medium_plants, message=error) + + +# QUERY: filter by height - tall +@app.route('/tall_plants', methods=['GET']) +def show_tall_plants(): + error = "" + display_tall_plants = db.session.query(Product, Category, PlantType, Size).select_from(Product). \ + join(Category).join(PlantType).join(Size).filter(Size.id == 4).order_by(Product.price.desc()).all() + return render_template('shop.html', display_tall_plants=display_tall_plants, message=error) + + +# QUERY: filter by type - cactus / succulent +@app.route('/cacti_succulent_plants', methods=['GET']) +def show_cacti_succulent_plants(): + error = "" + display_cacti_succulent_plants = db.session.query(Product, Category, PlantType, Size).select_from(Product). \ + join(Category).join(PlantType).join(Size).filter(PlantType.id == 1).order_by(Product.price.desc()).all() + return render_template('shop.html', display_cacti_succulent_plants=display_cacti_succulent_plants, message=error) + + +# QUERY: filter by type - hanging +@app.route('/hanging_plants', methods=['GET']) +def show_hanging_plants(): + error = "" + display_hanging_plants = db.session.query(Product, Category, PlantType, Size).select_from(Product). \ + join(Category).join(PlantType).join(Size).filter(PlantType.id == 2).order_by(Product.price.desc()).all() + return render_template('shop.html', display_hanging_plants=display_hanging_plants, message=error) + + +# QUERY: filter by type - flowering +@app.route('/flowering_plants', methods=['GET']) +def show_flowering_plants(): + error = "" + display_flowering_plants = db.session.query(Product, Category, PlantType, Size).select_from(Product). \ + join(Category).join(PlantType).join(Size).filter(PlantType.id == 3).order_by(Product.price.desc()).all() + return render_template('shop.html', display_flowering_plants=display_flowering_plants, message=error) + + +# QUERY: filter by type - palm +@app.route('/palm_plants', methods=['GET']) +def show_palm_plants(): + error = "" + display_palm_plants = db.session.query(Product, Category, PlantType, Size).select_from(Product). \ + join(Category).join(PlantType).join(Size).filter(PlantType.id == 4).order_by(Product.price.desc()).all() + return render_template('shop.html', display_palm_plants=display_palm_plants, message=error) + + +# QUERY: filter by type - fern +@app.route('/fern_plants', methods=['GET']) +def show_fern_plants(): + error = "" + display_fern_plants = db.session.query(Product, Category, PlantType, Size).select_from(Product). \ + join(Category).join(PlantType).join(Size).filter(PlantType.id == 5).order_by(Product.price.desc()).all() + return render_template('shop.html', display_fern_plants=display_fern_plants, message=error) + +# QUERY: filter by price +@app.route('/value_savers', methods=['GET']) +def show_value_saver(): + error = "" + display_value_saver = db.session.query(Product, Category, PlantType, Size).select_from(Product). \ + join(Category).join(PlantType).join(Size).filter(Product.price < 10).order_by(Product.price.desc()).all() + return render_template('shop.html', display_value_saver=display_value_saver, message=error) + +# QUERY: filter by price +@app.route('/modest_picks', methods=['GET']) +def show_modest_picks(): + error = "" + display_modest_picks = db.session.query(Product, Category, PlantType, Size).select_from(Product). \ + join(Category).join(PlantType).join(Size).filter(Product.price < 25).order_by(Product.price.desc()).all() + return render_template('shop.html', display_modest_picks=display_modest_picks, message=error) + +# QUERY: filter by price +@app.route('/fancy_picks', methods=['GET']) +def show_fancy_picks(): + error = "" + display_fancy_picks = db.session.query(Product, Category, PlantType, Size).select_from(Product). \ + join(Category).join(PlantType).join(Size).filter(Product.price < 55).order_by(Product.price.desc()).all() + return render_template('shop.html', display_fancy_picks=display_fancy_picks, message=error) + + +# QUERY: filter by price +@app.route('/premium_range', methods=['GET']) +def show_premium_range(): + error = "" + display_premium_range = db.session.query(Product, Category, PlantType, Size).select_from(Product). \ + join(Category).join(PlantType).join(Size).filter(Product.price > 56).order_by(Product.price.desc()).all() + return render_template('shop.html', display_premium_range=display_premium_range, message=error) + + +# Place an Order in progress, need to work out how to get the data out of the shopping cart +@app.route('/complete_order', methods=['GET', 'POST']) +def complete_order(): + error = "" + form = OrderForm() + + # if form.validate_on_submit(): + # flash(f' Order placed!', 'success') + # else: + # return render_template('cart.html', form=form) + + if request.method == 'POST': + cart_contents = session['cart'] + # print("cart contents", cart_contents) + # cart_contents is a list with multiple dictionaries in (if more than one type of item in the cart) + total_cost = 0 + # iterate through the dictionaries to get the values needed + for item in cart_contents: + person_id = session['id_number'] + order_date = date.today() + status_id = 1 + product_id = item['id'] + quantity = item['quantity'] + price_per_item= item['price'] + price_paid = price_per_item * quantity + total_cost += price_paid # need to work out how to get this from the shopping cart is going to be sum of all subtotals + + + # if messages left in for all form routes because may need to raise error here for validations that aren't currently showing + # if len(first_name) == 0 \ + # or len(last_name) == 0 \ + # or len(email) == 0\ + # or len(address_line_one) == 0\ + # or len(postcode) == 0\ + # or len(password) < 4\ + # or len(username) == 0: + # error = "Please complete each section of this form" + # else: + + # it is so close to working! just not autopopulating the order_header id + order_header = OrderHeader(person_id=person_id, order_date=order_date, status_id=status_id, + total_cost=total_cost) + + order_line = OrderLine(order_header=order_header, product_id=product_id, quantity=quantity, price_paid=price_paid) + # print("order header", order_header) + # print("order line", order_line) + + db.session.add(order_header) + db.session.add(order_line) + + db.session.commit() + session.pop('cart', default=None) + flash(f' Order successfully placed, enjoy your new plant friends!', 'success') + + return render_template('home.html', title='Home', message=error, form=EmailSignUpForm()) + return render_template('complete_order.html', title='Complete Order', message=error, form=form) + +@app.route('/update_customer_email', methods=['PUT', 'GET']) +@app.route('/customer//', methods=['PUT', 'GET']) +def update_customer_email(): + error = "" + form = UpdateEmailForm() + person_id = session['id_number'] + new_email = form.new_email.data + + if request.method == 'PUT': + person = Person.query.get(person_id) + person.email = new_email + db.session.commit() + + flash(f' You have updated your email address!', 'success') + + return render_template('home.html', message=error, title="Home") + return render_template('update_email.html', form=form, person_id=person_id, message=error, title='Update Email') + +# Victoria's code +# def register_basic_form(): +# error = "" +# form = BasicForm() +# +# if request.method == 'POST': +# first_name = form.first_name.data +# last_name = form.last_name.data +# +# if len(first_name) == 0 or len(last_name) == 0: +# error = "Please supply both first and last name" +# else: +# person = Person(first_name=first_name, last_name=last_name) +# db.session.add(person) +# db.session.commit() +# return 'Thank you!' +# return render_template('home.html', form=form, message=error, title='home') + +# @app.route('/cars', methods=['GET']) +# def show_cars(): +# error = "" +# cars = Car.query.all() +# if len(cars) == 0: +# error = "There are no cars to display" +# print(cars) +# return render_template('cars.html', cars=cars, message=error, title="Car") + +# @app.route('/people', methods=['GET']) +# def show_people(): +# error = "" +# people = Person.query.all() +# if len(people) == 0: +# error = "There are no people to display" +# print(people) +# return render_template('people.html', people=people, message=error) +# +# +# @app.route('/people/', methods=['GET']) +# def show_person(person_id): +# error = "" +# # use filter_by for any column +# # person = Person.query.filter_by(id=person_id).first() +# # use get for the PK +# person = Person.query.get(person_id) +# +# # simpsons = Person.query.filter_by(last_name="simpson").all() +# +# # to sort +# # simpsons = Person.query.filter_by(last_name="simpson").order_by(Person.first_name).all() +# # descending sort +# # simpsons = Person.query.filter_by(last_name="simpson").order_by(Person.first_name.desc()).all() +# # limit to top 2 simpsons +# simpsons = Person.query.filter_by(last_name="simpson").order_by(Person.first_name).limit(2).all() +# if not person: +# error = "There is no person with ID: " + str(person_id) +# print(person) +# return render_template('person.html', person=person, message=error, title="Person", family=simpsons) +# +# +# @app.route('/people/', methods=['PUT']) +# def update_person(person_id): +# error = "" +# person = Person.query.get(person_id) +# person.last_name = "Flanders" +# db.session.commit() +# if not person: +# error = "There is no person with ID: " + str(person_id) +# print(person) +# return render_template('person.html', person=person, message=error, title="Person", family=[]) +# +# +# @app.route('/people//', methods=['PUT']) +# def update_person_with_name(person_id, new_last_name): +# error = "" +# person = Person.query.get(person_id) +# person.last_name = new_last_name +# db.session.commit() +# if not person: +# error = "There is no person with ID: " + str(person_id) +# print(person) +# return render_template('person.html', person=person, message=error, title="Updated Person", family=[]) +# +# +# @app.route('/people/', methods=['DELETE']) +# def delete_person(person_id): +# error = "" +# person = Person.query.get(person_id) +# db.session.delete(person) +# db.session.commit() +# people = Person.query.all() +# if not person: +# error = "There is no person with ID: " + str(person_id) +# # print(person) +# return render_template('people.html', people=people, message=error, title="People") +# +# +# @app.route('/personandcars/', methods=['GET']) +# def people_and_cars(person_id): +# error = "" +# person = Person.query.get(person_id) +# # cars= person.cars +# if not person: +# error = "There is no person with ID: " + str(person_id) +# print(person) +# # print(person_and_carinfo) +# return render_template('person_and_cars.html', person=person, message=error, title="Person and Car Info") +# +# # return render_template('home.html', form=form, message=error) - # return render_template('home.html', form=form, message=error) \ No newline at end of file diff --git a/application/static/.DS_Store b/application/static/.DS_Store new file mode 100644 index 0000000..1c9f3ed Binary files /dev/null and b/application/static/.DS_Store differ diff --git a/application/static/images/Isabel.jpg b/application/static/images/Isabel.jpg new file mode 100644 index 0000000..feb3705 Binary files /dev/null and b/application/static/images/Isabel.jpg differ diff --git a/application/static/images/Parlour_palm_zoomout.jpg b/application/static/images/Parlour_palm_zoomout.jpg new file mode 100644 index 0000000..9c3125e Binary files /dev/null and b/application/static/images/Parlour_palm_zoomout.jpg differ diff --git a/application/static/images/aloe_vera.jpg b/application/static/images/aloe_vera.jpg new file mode 100644 index 0000000..56af822 Binary files /dev/null and b/application/static/images/aloe_vera.jpg differ diff --git a/application/static/images/aloe_vera_hand.jpg b/application/static/images/aloe_vera_hand.jpg new file mode 100644 index 0000000..47d0b93 Binary files /dev/null and b/application/static/images/aloe_vera_hand.jpg differ diff --git a/application/static/images/aloe_vera_pot.jpg b/application/static/images/aloe_vera_pot.jpg new file mode 100644 index 0000000..bbc9959 Binary files /dev/null and b/application/static/images/aloe_vera_pot.jpg differ diff --git a/application/static/images/alstromeria_pink.jpg b/application/static/images/alstromeria_pink.jpg new file mode 100644 index 0000000..618c1fa Binary files /dev/null and b/application/static/images/alstromeria_pink.jpg differ diff --git a/application/static/images/alstromeria_purple.jpg b/application/static/images/alstromeria_purple.jpg new file mode 100644 index 0000000..67d896c Binary files /dev/null and b/application/static/images/alstromeria_purple.jpg differ diff --git a/application/static/images/alstromeria_yellow.jpg b/application/static/images/alstromeria_yellow.jpg new file mode 100644 index 0000000..3374092 Binary files /dev/null and b/application/static/images/alstromeria_yellow.jpg differ diff --git a/application/static/images/anthurium.jpg b/application/static/images/anthurium.jpg new file mode 100644 index 0000000..2667276 Binary files /dev/null and b/application/static/images/anthurium.jpg differ diff --git a/application/static/images/anthurium_pot.jpg b/application/static/images/anthurium_pot.jpg new file mode 100644 index 0000000..a3bf19f Binary files /dev/null and b/application/static/images/anthurium_pot.jpg differ diff --git a/application/static/images/anthurium_white.jpg b/application/static/images/anthurium_white.jpg new file mode 100644 index 0000000..bd3055d Binary files /dev/null and b/application/static/images/anthurium_white.jpg differ diff --git a/application/static/images/boston_fern_bush.jpg b/application/static/images/boston_fern_bush.jpg new file mode 100644 index 0000000..b8e462f Binary files /dev/null and b/application/static/images/boston_fern_bush.jpg differ diff --git a/application/static/images/boston_fern_single.jpg b/application/static/images/boston_fern_single.jpg new file mode 100644 index 0000000..cc847e2 Binary files /dev/null and b/application/static/images/boston_fern_single.jpg differ diff --git a/application/static/images/cactus_icon.jpg b/application/static/images/cactus_icon.jpg new file mode 100644 index 0000000..731e0ff Binary files /dev/null and b/application/static/images/cactus_icon.jpg differ diff --git a/application/static/images/climbing_rose_1.jpg b/application/static/images/climbing_rose_1.jpg new file mode 100644 index 0000000..bbf194e Binary files /dev/null and b/application/static/images/climbing_rose_1.jpg differ diff --git a/application/static/images/climbing_rose_2.jpg b/application/static/images/climbing_rose_2.jpg new file mode 100644 index 0000000..ac8f4f3 Binary files /dev/null and b/application/static/images/climbing_rose_2.jpg differ diff --git a/application/static/images/climbing_rose_3.jpg b/application/static/images/climbing_rose_3.jpg new file mode 100644 index 0000000..340ad82 Binary files /dev/null and b/application/static/images/climbing_rose_3.jpg differ diff --git a/application/static/images/dead_plant_1.jpg b/application/static/images/dead_plant_1.jpg new file mode 100644 index 0000000..498be26 Binary files /dev/null and b/application/static/images/dead_plant_1.jpg differ diff --git a/application/static/images/dead_plant_2.jpg b/application/static/images/dead_plant_2.jpg new file mode 100644 index 0000000..14c514f Binary files /dev/null and b/application/static/images/dead_plant_2.jpg differ diff --git a/application/static/images/dead_plant_3.jpg b/application/static/images/dead_plant_3.jpg new file mode 100644 index 0000000..c5c2749 Binary files /dev/null and b/application/static/images/dead_plant_3.jpg differ diff --git a/application/static/images/fatsia_japonica_berry.jpg b/application/static/images/fatsia_japonica_berry.jpg new file mode 100644 index 0000000..fc7531f Binary files /dev/null and b/application/static/images/fatsia_japonica_berry.jpg differ diff --git a/application/static/images/fatsia_japonica_leaf.jpg b/application/static/images/fatsia_japonica_leaf.jpg new file mode 100644 index 0000000..5d13441 Binary files /dev/null and b/application/static/images/fatsia_japonica_leaf.jpg differ diff --git a/application/static/images/general_rose_1.jpg b/application/static/images/general_rose_1.jpg new file mode 100644 index 0000000..ae93bfc Binary files /dev/null and b/application/static/images/general_rose_1.jpg differ diff --git a/application/static/images/general_rose_2.jpg b/application/static/images/general_rose_2.jpg new file mode 100644 index 0000000..35034a9 Binary files /dev/null and b/application/static/images/general_rose_2.jpg differ diff --git a/application/static/images/general_rose_3.jpg b/application/static/images/general_rose_3.jpg new file mode 100644 index 0000000..183c2cf Binary files /dev/null and b/application/static/images/general_rose_3.jpg differ diff --git a/application/static/images/green_leaves.jpg b/application/static/images/green_leaves.jpg new file mode 100644 index 0000000..c8ec852 Binary files /dev/null and b/application/static/images/green_leaves.jpg differ diff --git a/application/static/images/header_about_us.png b/application/static/images/header_about_us.png new file mode 100644 index 0000000..8aaf94b Binary files /dev/null and b/application/static/images/header_about_us.png differ diff --git a/application/static/images/header_contact_us.png b/application/static/images/header_contact_us.png new file mode 100644 index 0000000..009c48e Binary files /dev/null and b/application/static/images/header_contact_us.png differ diff --git a/application/static/images/header_plant_care.png b/application/static/images/header_plant_care.png new file mode 100644 index 0000000..53627b5 Binary files /dev/null and b/application/static/images/header_plant_care.png differ diff --git a/application/static/images/header_plant_care_flip.png b/application/static/images/header_plant_care_flip.png new file mode 100644 index 0000000..45a8941 Binary files /dev/null and b/application/static/images/header_plant_care_flip.png differ diff --git a/application/static/images/header_shop_1.png b/application/static/images/header_shop_1.png new file mode 100644 index 0000000..7227e1f Binary files /dev/null and b/application/static/images/header_shop_1.png differ diff --git a/application/static/images/header_shop_2.png b/application/static/images/header_shop_2.png new file mode 100644 index 0000000..0e4f760 Binary files /dev/null and b/application/static/images/header_shop_2.png differ diff --git a/application/static/images/header_shopping_cart.png b/application/static/images/header_shopping_cart.png new file mode 100644 index 0000000..fb074d7 Binary files /dev/null and b/application/static/images/header_shopping_cart.png differ diff --git a/application/static/images/hydrangea_dusky_pink.jpg b/application/static/images/hydrangea_dusky_pink.jpg new file mode 100644 index 0000000..8f6020d Binary files /dev/null and b/application/static/images/hydrangea_dusky_pink.jpg differ diff --git a/application/static/images/hydrangea_hot_pink.jpg b/application/static/images/hydrangea_hot_pink.jpg new file mode 100644 index 0000000..9922e4c Binary files /dev/null and b/application/static/images/hydrangea_hot_pink.jpg differ diff --git a/application/static/images/hydrangea_white.jpg b/application/static/images/hydrangea_white.jpg new file mode 100644 index 0000000..34a3aa9 Binary files /dev/null and b/application/static/images/hydrangea_white.jpg differ diff --git a/application/static/images/jodie_about_us.jpg b/application/static/images/jodie_about_us.jpg new file mode 100644 index 0000000..f1be321 Binary files /dev/null and b/application/static/images/jodie_about_us.jpg differ diff --git a/application/static/images/jody_leaf.jpg b/application/static/images/jody_leaf.jpg new file mode 100644 index 0000000..a077f73 Binary files /dev/null and b/application/static/images/jody_leaf.jpg differ diff --git a/application/static/images/lifestyle1.jpg b/application/static/images/lifestyle1.jpg new file mode 100644 index 0000000..f09ca9c Binary files /dev/null and b/application/static/images/lifestyle1.jpg differ diff --git a/application/static/images/lifestyle2.jpg b/application/static/images/lifestyle2.jpg new file mode 100644 index 0000000..832c53c Binary files /dev/null and b/application/static/images/lifestyle2.jpg differ diff --git a/application/static/images/lifestyle3.jpg b/application/static/images/lifestyle3.jpg new file mode 100644 index 0000000..8c0c920 Binary files /dev/null and b/application/static/images/lifestyle3.jpg differ diff --git a/application/static/images/lifestyle4.jpg b/application/static/images/lifestyle4.jpg new file mode 100644 index 0000000..20011ea Binary files /dev/null and b/application/static/images/lifestyle4.jpg differ diff --git a/application/static/images/lifestyle5.jpg b/application/static/images/lifestyle5.jpg new file mode 100644 index 0000000..2e1ff07 Binary files /dev/null and b/application/static/images/lifestyle5.jpg differ diff --git a/application/static/images/logoleaves.jpg b/application/static/images/logoleaves.jpg new file mode 100644 index 0000000..1e9d6f0 Binary files /dev/null and b/application/static/images/logoleaves.jpg differ diff --git a/application/static/images/parlour_palm.jpg b/application/static/images/parlour_palm.jpg new file mode 100644 index 0000000..54f9345 Binary files /dev/null and b/application/static/images/parlour_palm.jpg differ diff --git a/application/static/images/parlour_palm_close.jpg b/application/static/images/parlour_palm_close.jpg new file mode 100644 index 0000000..c8869e6 Binary files /dev/null and b/application/static/images/parlour_palm_close.jpg differ diff --git a/application/static/images/plant_emporium_favicon.png b/application/static/images/plant_emporium_favicon.png new file mode 100644 index 0000000..eec0918 Binary files /dev/null and b/application/static/images/plant_emporium_favicon.png differ diff --git a/application/static/images/plant_emporium_logo.png b/application/static/images/plant_emporium_logo.png new file mode 100644 index 0000000..2d51c0d Binary files /dev/null and b/application/static/images/plant_emporium_logo.png differ diff --git a/application/static/images/spiky_succulent.jpg b/application/static/images/spiky_succulent.jpg new file mode 100644 index 0000000..51430c4 Binary files /dev/null and b/application/static/images/spiky_succulent.jpg differ diff --git a/application/static/images/succulent_in_tin.jpg b/application/static/images/succulent_in_tin.jpg new file mode 100644 index 0000000..e035b2e Binary files /dev/null and b/application/static/images/succulent_in_tin.jpg differ diff --git a/application/static/images/succulent_top_down.jpg b/application/static/images/succulent_top_down.jpg new file mode 100644 index 0000000..56fd0a9 Binary files /dev/null and b/application/static/images/succulent_top_down.jpg differ diff --git a/application/static/images/sweet_orange_tree_1.jpg b/application/static/images/sweet_orange_tree_1.jpg new file mode 100644 index 0000000..10e4575 Binary files /dev/null and b/application/static/images/sweet_orange_tree_1.jpg differ diff --git a/application/static/images/sweet_orange_tree_2.jpg b/application/static/images/sweet_orange_tree_2.jpg new file mode 100644 index 0000000..133e8ef Binary files /dev/null and b/application/static/images/sweet_orange_tree_2.jpg differ diff --git a/application/static/images/sweet_orange_tree_3.jpg b/application/static/images/sweet_orange_tree_3.jpg new file mode 100644 index 0000000..3796b92 Binary files /dev/null and b/application/static/images/sweet_orange_tree_3.jpg differ diff --git a/application/static/images/swiss_cheese_plant.jpg b/application/static/images/swiss_cheese_plant.jpg new file mode 100644 index 0000000..6d89254 Binary files /dev/null and b/application/static/images/swiss_cheese_plant.jpg differ diff --git a/application/static/images/swiss_cheese_plant_close.jpg b/application/static/images/swiss_cheese_plant_close.jpg new file mode 100644 index 0000000..d90a1ef Binary files /dev/null and b/application/static/images/swiss_cheese_plant_close.jpg differ diff --git a/application/static/images/swiss_cheese_plant_small.jpg b/application/static/images/swiss_cheese_plant_small.jpg new file mode 100644 index 0000000..54692bb Binary files /dev/null and b/application/static/images/swiss_cheese_plant_small.jpg differ diff --git a/application/static/images/three_pots_succulents.jpg b/application/static/images/three_pots_succulents.jpg new file mode 100644 index 0000000..c3cf170 Binary files /dev/null and b/application/static/images/three_pots_succulents.jpg differ diff --git a/application/static/styles.css b/application/static/styles.css index 9eb8697..1dbcab1 100644 --- a/application/static/styles.css +++ b/application/static/styles.css @@ -1,27 +1,380 @@ body{ width: 90%; margin: auto; - font-family: "Helvetica Neue"; - background-color: lightblue; + font-family: "Raleway", sans-serif; + background-color: #F0EDE1; + color: #0A451B; + font-size: 18px; } h1 { font-family: verdana; - color: white; + color: #2E6B28; text-align: center; } p { - font-family: verdana; - font-size: 24px; + font-family: "Raleway", sans-serif; + color: #0A451B } -footer{ - font-size: 1.2em; + +footer { + padding-top: 20px; + padding-bottom: 50px; + font-size: 1 em; text-align: center; color: gray; -} + font-family: "Raleway", sans-serif; + background-color: #F0EDE1; .error_message{ font-size: 1.3em; color: red; +} + +} +/*Home page heading */ +/* Container needed to position the button. Width auto so it aligns with nav */ +.container-home { + position: relative; + width: auto; +} + +/* Make the image responsive */ +.container-home img { + width: 100%; + height: 100%; + min-height: 70%; + opacity: 70%; +} + +a { + color: white; + } + +a:link { + color: #2E6B28; + +} + +a:visited { + color: #2E6B28; + +} + +/* Styling the buttons and place it in the middle of the container/image */ +.container-home .btn1 { + position: absolute; + top: 80%; + left: 30%; + transform: translate(-20%, -20%); + -ms-transform: translate(-50%, -50%); + background-color: #C9C1AD; + color: white; + font-size: 30px; + padding: 12px 24px; + border: none; + cursor: pointer; + border-radius: 5px; + } + +.container-home .btn2 { + position: absolute; + top: 80%; + left: 50%; + transform: translate(-20%, -20%); + -ms-transform: translate(-50%, -50%); + background-color: #C9C1AD; + color: white; + font-size: 30px; + padding: 12px 24px; + border: none; + cursor: pointer; + border-radius: 5px; + } + + +.container-home .btn1:hover { + background-color: #2E6B28; +} + +.container-home .btn2:hover { + background-color: #2E6B28; +} + + +.container-home h1 { +position: absolute; + top: 15%; + left: 50%; + right: 50%; + color: #2E6B28; + font-family: "Raleway", sans-serif; + weight: 600px; + font-size: 90px; + text-align: center; + width: 100px; + +} + +.container-home h2 { +position: absolute; + top: 55%; + left: 50%; + font-family: "Raleway", sans-serif; + weight: 600px; + font-size: 50px; + text-align: center; + color: #0A451B; + +} + +/* newsletter container styling on homepage */ +.newsletter-home { + padding-top: 50px; + text-align: center; + background-color: #DDD8C7 +} + +.newsletter-home h4 { + font-size: 40px; +} +.newsletter-home p { + font-size: 20px; +} + + + + +/* image for the about us page */ +.container-about { + position: relative; + width: auto; +} + + +.container-about img { + width: 100%; + height: 100%; + min-height: 70%; + opacity: 70%; +} + +/* getting text on about page postioned */ +.container-about h1 { +position: absolute; + top: 15%; + left: 50%; + right: 50%; + color: #2E6B28; + font-family: "Raleway", sans-serif; + weight: 600px; + font-size: 5rem; + text-align: center; + width: 100px; + +} + +a { + color: white; + } + + + /* custom 404 page heading */ +/* Container needed to position the button. Width auto so it aligns with nav */ +.container-404 { + position: relative; + width: auto; +} + + +/* Make the image responsive */ +.container-404 img { + width: 100%; + height: 100%; + min-height: 70%; + opacity: 70%; +} + +/* Styling the buttons and place it in the middle of the container/image */ +.container-404 .btn1 { + position: absolute; + top: 80%; + left: 30%; + transform: translate(-20%, -20%); + -ms-transform: translate(-50%, -50%); + background-color: #C9C1AD; + color: white; + font-size: 30px; + padding: 12px 24px; + border: none; + cursor: pointer; + border-radius: 5px; + } + +.container-404 .btn2 { + position: absolute; + top: 80%; + left: 50%; + transform: translate(-20%, -20%); + -ms-transform: translate(-50%, -50%); + background-color: #C9C1AD; + color: white; + font-size: 30px; + padding: 12px 24px; + border: none; + cursor: pointer; + border-radius: 5px; + } + + +.container-404 .btn1:hover { + background-color: #2E6B28; +} + +.container-404 .btn2:hover { + background-color: #2E6B28; +} + + +.container-404 h1 { +position: absolute; + top: 15%; + left: 50%; + right: 50%; + color: #F0EDE1; + font-family: "Raleway", sans-serif; + weight: 600px; + font-size: 90px; + text-align: center; + width: 100px; + +} + +.container-404 h2 { +position: absolute; + top: 55%; + left: 50%; + font-family: "Raleway", sans-serif; + weight: 600px; + font-size: 50px; + text-align: center; + color: #F0EDE1; + +} + +/* shopping cart page*/ +.container-cart img { + width: 100%; + height: 100%; + min-height: 70%; + opacity: 70%; +} + +/* image for the shopping cart page */ +.container-cart { + position: relative; + width: auto; +} + +/* getting text on cart page postioned */ +.container-cart h1 { +position: absolute; + top: 15%; + left: 50%; + right: 50%; + color: #2E6B28; + font-family: "Raleway", sans-serif; + weight: 600px; + font-size: 5rem; + text-align: center; + width: 100px; + +} + +/* blog page*/ +.container-blog img { + width: 100%; + height: 100%; + min-height: 70%; + opacity: 70%; +} + +/* image for the blog page */ +.container-blog { + position: relative; + width: auto; +} + +/* getting text on blog postioned */ +.container-blog h1 { +position: absolute; + top: 15%; + left: 50%; + right: 50%; + color: #2E6B28; + font-family: "Raleway", sans-serif; + weight: 600px; + font-size: 5rem; + text-align: center; + width: 100px; + +} + +/* contact us page*/ +.container-contact img { + width: 100%; + height: 100%; + min-height: 70%; + opacity: 70%; +} + +/* image for the contact page */ +.container-contact { + position: relative; + width: auto; +} + +/* getting text on contact page postioned */ +.container-contact h1 { +position: absolute; + top: 15%; + left: 50%; + right: 50%; + color: #F0EDE1; + font-family: "Raleway", sans-serif; + weight: 600px; + font-size: 5rem; + text-align: center; + width: 100px; + +} + +/* shop page*/ +.container-shop img { + width: 100%; + height: 100%; + min-height: 70%; + opacity: 70%; +} + +/* image for the shop page */ +.container-shop { + position: relative; + width: auto; +} + +/* getting text on shop page postioned */ +.container-shop h1 { +position: absolute; + top: 15%; + left: 50%; + right: 50%; + color: #F0EDE1; + font-family: "Raleway", sans-serif; + weight: 600px; + font-size: 5rem; + text-align: center; + width: 100px; + } \ No newline at end of file diff --git a/application/templates/about.html b/application/templates/about.html new file mode 100644 index 0000000..4fa770e --- /dev/null +++ b/application/templates/about.html @@ -0,0 +1,56 @@ +{% extends "layout.html" %} +{% block body_content %} + +
+ plants +

All About Us

+ + +
+ + +
+

The Plant Emporium features a carefully-curated selection of indoor and outdoor plants that are ideal for both the home and office. Each plant boasts an elegance and simplicity that echo the Plant Emporium ethos, with air cleaning properties for a healthy and aesthetic solution. Add vibrancy and life to any indoor or outdoor space, with our range of plants and explore great tips to care for them. Explore our range of Plant Emporium plants and select one to brighten up your space!

+ +

Meet the Team

+ + +
+ + +
+
+ Card image cap +
+
Jody
+
The Plant Doctor
+

Jody really kills too many plants to claim this title

+

She is getting better though

+
+
+
+ Card image cap +
+
Jodie
+

This card has supporting text below as a natural lead-in to additional content.

+

Last updated 3 mins ago

+
+
+
+ Card image cap +
+
Card title
+

This is a wider card with supporting text below as a natural lead-in to additional content. This card has even longer content than the first to show that equal height action.

+

Last updated 3 mins ago

+
+
+
+ Card image cap +
+
Card title
+

This is a wider card with supporting text below as a natural lead-in to additional content. This card has even longer content than the first to show that equal height action.

+

Last updated 3 mins ago

+
+
+
+{% endblock %} \ No newline at end of file diff --git a/application/templates/add_to_cart.html b/application/templates/add_to_cart.html new file mode 100644 index 0000000..3a43dd4 --- /dev/null +++ b/application/templates/add_to_cart.html @@ -0,0 +1,56 @@ +{% extends "layout.html" %} +{% block body_content %} + +
+ three small succulent plants in white ceramic pots +

Shopping Cart

+ +
+ +{% if session['logged_in_username'] %} +
+

Welcome {{ session['logged_in_username'] }}!

+

Are you logged in? That is {{ session['logged_in'] }}

+

What type of log in is it? You are logged in as {{ session['typesession'] }}

+
+
+{% else %} +
+

You are not currently logged in

+

Please Login to make a purchase

+ +
+
+ +{% endif %} + +
+
+ {{ form.hidden_tag() }} +
+ Add Plant to your cart +
Here, you'll be able to:
+
  • Add a plant to your shopping cart
  • +
    +
    + {{ form.product.label(class="form-control-label") }} + {{ form.product(class="form-control form-control-lg", placeholder="e.g. Boston Fern") }} +
    +
    + {{ form.quantity.label(class="form-control-label") }} + {{ form.quantity(class="form-control form-control-lg") }} +
    + + + + +
    +
    +
    + {{ form.submit(class="btn btn-secondary") }} +
    + +
    +
    + +{% endblock %} \ No newline at end of file diff --git a/application/templates/addpost.html b/application/templates/addpost.html new file mode 100644 index 0000000..b903805 --- /dev/null +++ b/application/templates/addpost.html @@ -0,0 +1,33 @@ +{% extends "layout.html" %} +{% block body_content %} + +
    +
    + {{ form.hidden_tag() }} +
    + Add a blogpost +
    Here, you'll be able to:
    +
  • Add a new blogpost!
  • + +
    +
    + {{ form.title.label(class="form-control-label") }} + {{ form.title(class="form-control form-control-lg") }} +
    +
    + {{ form.author.label(class="form-control-label") }} + {{ form.author(class="form-control form-control-lg") }} +
    +
    + {{ form.post_content.label(class="form-control-label") }} + {{ form.post_content(class="form-control form-control-lg") }} +
    +
    +
    + {{ form.submit }} +
    + +
    +
    + +{% endblock %} \ No newline at end of file diff --git a/application/templates/cart.html b/application/templates/cart.html new file mode 100644 index 0000000..ee8c049 --- /dev/null +++ b/application/templates/cart.html @@ -0,0 +1,115 @@ +{% extends "layout.html" %} +{% block body_content %} + +
    + three small succulent plants in white ceramic pots +

    Shopping Cart

    + +
    + +
    + +{% if cart_contents != [] %} +

    What good taste you have! Currently in your cart:

    + +
    + + + + {% for header in headings %} + + {% endfor %} + + + + + {% for value in cart_contents %} + + {% if value.id == 1 %} + + {% endif %} + {% if value.id == 2 %} + + {% endif %} + {% if value.id == 3 %} + + {% endif %} + {% if value.id == 4 %} + + {% endif %} + {% if value.id == 5 %} + + {% endif %} + {% if value.id == 6 %} + + {% endif %} + {% if value.id == 7 %} + + {% endif %} + {% if value.id == 8 %} + + {% endif %} + {% if value.id == 9 %} + + {% endif %} + {% if value.id == 10 %} + + {% endif %} + + + + + + + + + {% endfor %} + + + + + + + + + +
    {{ header }}
    Boston Fern Image 1Aloe VeraParlour PalmAnthurium in a potSwiss Cheese PlantSweet Orange TreeClimbing RoseFatsia Japonica LeafWhite HydrangeaYellow Alstromeria{{ value.plant_nickname }}{{ value.species}}£{{ value.price }}{{ value.quantity }}£{{ (value.sub_total) }}
    Total price: £{{ cart_contents|sum('sub_total')}}
    +
    + +
    + + + +

    Placing an order

    +

    When you click Place Order your order is placed using the contact details linked to your account.

    + + + + +
    +
    + {{ form.hidden_tag() }} + {{ form.csrf_token() }} +
    +
    +
    +
    + + +
    +
    + +
    + {{ form.submit(class="btn btn-success ml-2 btn-lg") }} +
    +
    + +
    + +{% else %} + +

    Your cart is currently empty! Why not visit our shop for some inspiration?

    + +{% endif %} + +{% endblock %} \ No newline at end of file diff --git a/application/templates/cart_success.html b/application/templates/cart_success.html new file mode 100644 index 0000000..1032281 --- /dev/null +++ b/application/templates/cart_success.html @@ -0,0 +1,152 @@ +{% extends "layout.html" %} +{% block body_content %} + +
    + three small succulent plants in white ceramic pots +

    Shopping Cart

    + +
    + +
    + +

    You just added to your cart:

    + +
    + + + + + + {% if attributeObject.id == 1 %} + + {% endif %} + {% if attributeObject.id == 2 %} + + {% endif %} + {% if attributeObject.id == 3 %} + + {% endif %} + {% if attributeObject.id == 4 %} + + {% endif %} + {% if attributeObject.id == 5 %} + + {% endif %} + {% if attributeObject.id == 6 %} + + {% endif %} + {% if attributeObject.id == 7 %} + + {% endif %} + {% if attributeObject.id == 8 %} + + {% endif %} + {% if attributeObject.id == 9 %} + + {% endif %} + {% if attributeObject.id == 10 %} + + {% endif %} + + + + + + + + + +
    Boston Fern Image 1Aloe VeraParlour PalmAnthurium in a potSwiss Cheese PlantSweet Orange TreeClimbing RoseFatsia Japonica LeafWhite HydrangeaYellow Alstromeria{{ attributeObject.plant_nickname}}{{ attributeObject.species}}Price for this is £{{ attributeObject.price }} per itemSub-total is £{{ attributeObject.sub_total }}Quantity added to cart {{ attributeObject.quantity }}
    +
    +
    + + +
    +
    + +
    +

    What good taste you have! Currently in your cart:

    + +
    + + + + {% for header in headings %} + + {% endfor %} + + + + + {% for value in cart_contents %} + + {% if value.id == 1 %} + + {% endif %} + {% if value.id == 2 %} + + {% endif %} + {% if value.id == 3 %} + + {% endif %} + {% if value.id == 4 %} + + {% endif %} + {% if value.id == 5 %} + + {% endif %} + {% if value.id == 6 %} + + {% endif %} + {% if value.id == 7 %} + + {% endif %} + {% if value.id == 8 %} + + {% endif %} + {% if value.id == 9 %} + + {% endif %} + {% if value.id == 10 %} + + {% endif %} + + + + + + + + {% endfor %} + + + + + + + + + + +
    {{ header }}
    Boston Fern Image 1Aloe VeraParlour PalmAnthurium in a potSwiss Cheese PlantSweet Orange TreeClimbing RoseFatsia Japonica LeafWhite HydrangeaYellow Alstromeria{{ value.plant_nickname }}{{ value.species}}£{{ value.price }}{{ value.quantity }}£{{ (value.sub_total) }}
    Total price: £{{ cart_contents|sum('sub_total')}}
    +
    + + + + +
    + +

    Checking Out

    +

    Click Checkout when you have everything that you need!

    + + +
    + + +
    + + + +{% endblock %} \ No newline at end of file diff --git a/application/templates/complete_order.html b/application/templates/complete_order.html new file mode 100644 index 0000000..6b704e4 --- /dev/null +++ b/application/templates/complete_order.html @@ -0,0 +1,20 @@ +{% extends "layout.html" %} +{% block body_content %} + +trying to get place order button working here +
    +
    + {{ form.hidden_tag() }} + {{ form.csrf_token() }} +
    +
    +
    + {{ form.submit(class="btn btn-secondary") }} +
    +
    + +
    + + + +{% endblock %} \ No newline at end of file diff --git a/application/templates/contact_us.html b/application/templates/contact_us.html new file mode 100644 index 0000000..071433b --- /dev/null +++ b/application/templates/contact_us.html @@ -0,0 +1,31 @@ +{% extends "layout.html" %} +{% block body_content %} + + +
    + plants +

    Contact Us

    + + +
    +

    Contact Us

    + +

    You can reach us by the following methods

    + +

    Phone:

    +

    0208555444

    +

    Email:

    +info@plantemporium.com +

    Address:

    +

    The Plant Emporium
    +Sky Studios
    +Grant Way,
    +Isleworth
    +TW7 5QD

    + + +

    Locate us:

    +

    + + +{% endblock %} \ No newline at end of file diff --git a/application/templates/customer_list.html b/application/templates/customer_list.html new file mode 100644 index 0000000..96254c7 --- /dev/null +++ b/application/templates/customer_list.html @@ -0,0 +1,15 @@ +{% extends "layout.html" %} +{% block body_content %} + Customer List + + +
    +{% for customer in customer %} +

    {{customer.id}} {{customer.first_name}} {{customer.last_name}} {{customer.email}}

    +{% endfor %} +
    + {{ message }} +
    + + +{% endblock %} \ No newline at end of file diff --git a/application/templates/customer_orders.html b/application/templates/customer_orders.html new file mode 100644 index 0000000..7d22128 --- /dev/null +++ b/application/templates/customer_orders.html @@ -0,0 +1,53 @@ +{% extends "layout.html" %} +{% block body_content %} + Customer Orders + + +
    + + +
    + {{ message }} +
    + +
    +

    Customer Orders

    + +
    +
    + + + + {% for header in headings %} + + {% endfor %} + + + + + {% for customer, order, order_status, order_detail, product in customer_orders %} + + + + + + + + + + + {% endfor %} + + +
    {{ header }}
    {{order.id}}{{customer.first_name}} {{customer.last_name}}{{order.order_date}}{{order_status.status_description}}{{product.species}}{{order_detail.quantity}}
    +
    + +
    + +
    + + + + + +{% endblock %} \ No newline at end of file diff --git a/application/templates/delete_blogpost.html b/application/templates/delete_blogpost.html new file mode 100644 index 0000000..9e4a3a9 --- /dev/null +++ b/application/templates/delete_blogpost.html @@ -0,0 +1,28 @@ +{% extends "layout.html" %} +{% block body_content %} + +
    +
    + {{ form.hidden_tag() }} + {{ form.csrf_token() }} + +
    + Delete a blogpost +
    Here, you'll be able to:
    +
  • Delete a blogpost!
  • + +
    +
    + {{ form.id.label(class="form-control-label") }} + {{ form.id(class="form-control form-control-lg") }} +
    + +
    +
    + {{ form.submit }} +
    + +
    +
    + +{% endblock %} \ No newline at end of file diff --git a/application/templates/home.html b/application/templates/home.html index 6e0f40d..ebb8a0a 100644 --- a/application/templates/home.html +++ b/application/templates/home.html @@ -1,22 +1,35 @@ - - - - - Simple Form - - -
    +{% extends "layout.html" %} +{% block body_content %} + + + + +
    + leaves +

    The Plant Emporium

    +

    Plants for every space

    + + +
    + + + + + + + +{% endblock %} +
    \ No newline at end of file diff --git a/application/templates/layout.html b/application/templates/layout.html index 446d9be..60e1f44 100644 --- a/application/templates/layout.html +++ b/application/templates/layout.html @@ -1,16 +1,324 @@ - + + + + + + + + {{title}} - Page - + + + + + -

    {{ title }} Page

    + +{% if session['typesession'] == 'staff' and session['logged_in'] == True %} + + +{% elif session['typesession'] == 'customer' and session['logged_in'] == True %} + + + +{% else %} + + + + +{% endif %} + + + + {% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} + {% for category, message in messages %} +
    + {{ message }} +
    + {% endfor %} + {% endif %} + {% endwith %} {% block body_content %}{% endblock %}
    {% block footer_content %}{% endblock %} + +
    + +

    © 2022 The Plant Emporium, brought to you by Team Yellow

    + +
    + + + + + + + + + diff --git a/application/templates/login.html b/application/templates/login.html new file mode 100644 index 0000000..7a03e52 --- /dev/null +++ b/application/templates/login.html @@ -0,0 +1,40 @@ +{% extends "layout.html" %} + +{% block body_content %} + + + + Plant Emporium - login page + + + + +
    +

    Please login

    +
    +
    +
    + {{ form.username.label(class="form-control-label") }} + {{ form.username(class="form-control form-control-lg", placeholder="Username") }} +
    +
    + {{ form.password.label(class="form-control-label") }} + {{ form.password(class="form-control form-control-lg", placeholder="Password") }} +
    + + +
    + {{ form.submit(class="btn btn-secondary") }} +
    + + +
    + {% if error %} +

    Error: {{ error }} + {% endif %} +

    + + + + +{% endblock %} \ No newline at end of file diff --git a/application/templates/order_history.html b/application/templates/order_history.html new file mode 100644 index 0000000..b926542 --- /dev/null +++ b/application/templates/order_history.html @@ -0,0 +1,53 @@ +{% extends "layout.html" %} +{% block body_content %} + Order History + + +
    + + + + +
    +

    Your Previous Orders

    + +
    +
    + + + + {% for header in headings %} + + {% endfor %} + + + + + {% for order_header, order_status, order_detail, product in customer_order_history %} + + + + + + + + + + {% endfor %} + + +
    {{ header }}
    {{ order_header.id }}{{ order_status.status_description}} {{ order_header.order_date }}{{product.species}}{{order_detail.quantity }} £{{ order_detail.price_paid }}
    +
    + +
    + +
    + + + +
    + {{ message }} +
    + + +{% endblock %} \ No newline at end of file diff --git a/application/templates/outstanding_orders.html b/application/templates/outstanding_orders.html new file mode 100644 index 0000000..0bc8881 --- /dev/null +++ b/application/templates/outstanding_orders.html @@ -0,0 +1,51 @@ +{% extends "layout.html" %} +{% block body_content %} + Outstanding Orders + + +
    + +

    + +
    + {{ message }} +
    + + + + +
    +

    Orders that need packing and shipping

    + +
    +
    + + + + {% for header in headings %} + + {% endfor %} + + + + + {% for order, order_status, order_detail, product in outstanding_orders %} + + + + + + + + + + {% endfor %} + + +
    {{ header }}
    {{order.id}}{{order.order_date}} {{order_status.status_description}}{{product.species}}{{order_detail.quantity}}
    +
    + +
    + +
    +{% endblock %} \ No newline at end of file diff --git a/application/templates/page_not_found.html b/application/templates/page_not_found.html new file mode 100644 index 0000000..28d1d76 --- /dev/null +++ b/application/templates/page_not_found.html @@ -0,0 +1,13 @@ +{% extends "layout.html" %} +{% block body_content %} + + +
    + dead plant and sad looking lady +

    Oh No!

    +

    Looks like that's a dead link, sorry!

    + + +
    + +{% endblock %} \ No newline at end of file diff --git a/application/templates/plant.html b/application/templates/plant.html new file mode 100644 index 0000000..23d7376 --- /dev/null +++ b/application/templates/plant.html @@ -0,0 +1,391 @@ +{% extends "layout.html" %} +{% block body_content %} + + +
    +
    + +
    + + + + + {% if plant.id == 1 %} +
    + {% endif %} +
    + + {% if plant.id == 1 %} +
    + Boston Fern Image 1 +
    + {% endif %} +
    + +
    + {% if plant.id == 1 %} +
    + Boston Fern Image 2 +
    + {% endif %} + + {% if plant.id == 1 %} +
    + Boston Fern Image 3 +
    + {% endif %} +
    + + + {% if plant.id == 2 %} +
    + {% endif %} + +
    + {% if plant.id == 2 %} +
    + Aloe Vera Image 1 +
    + {% endif %} +
    + +
    + {% if plant.id == 2 %} +
    + Aloe Vera Image 2 +
    + {% endif %} + + {% if plant.id == 2 %} +
    + Aloe Vera Image 3 +
    + {% endif %} +
    + + + {% if plant.id == 3 %} +
    + {% endif %} +
    + + {% if plant.id == 3 %} +
    + Parlour palm Image 1 +
    + {% endif %} +
    + +
    + {% if plant.id == 3 %} +
    + Parlour palm Image 2 +
    + {% endif %} + + {% if plant.id == 3 %} +
    + Parlour palm Image 3 +
    + {% endif %} +
    + + + {% if plant.id == 4 %} +
    + {% endif %} +
    + + {% if plant.id == 4 %} +
    + Anthurium Image 1 +
    + {% endif %} +
    + +
    + {% if plant.id == 4 %} +
    + Anthurium Image 2 +
    + {% endif %} + + {% if plant.id == 4 %} +
    + Anthurium Image 3 +
    + {% endif %} +
    + + + {% if plant.id == 5 %} +
    + {% endif %} +
    + + {% if plant.id == 5 %} +
    + Swiss Cheese Plant Image 1 +
    + {% endif %} +
    + +
    + {% if plant.id == 5 %} +
    + Swiss Cheese Plant Image 2 +
    + {% endif %} + + {% if plant.id == 5 %} +
    + Swiss Cheese Plant Image 3 +
    + {% endif %} +
    + + + {% if plant.id == 6 %} +
    + {% endif %} +
    + + {% if plant.id == 6 %} +
    + Sweet Orange Tree Image 1 +
    + {% endif %} +
    + +
    + {% if plant.id == 6 %} +
    + Sweet Orange Tree Image 2 +
    + {% endif %} + + {% if plant.id == 6 %} +
    + Sweet Orange Tree Image 3 +
    + {% endif %} +
    + + + {% if plant.id == 7 %} +
    + {% endif %} +
    + + {% if plant.id == 7 %} +
    + Climbing Rose Image 1 +
    + {% endif %} +
    + +
    + {% if plant.id == 7 %} +
    + Climbing Rose Image 2 +
    + {% endif %} + + {% if plant.id == 7 %} +
    + Climbing Rose Image 3 +
    + {% endif %} +
    + + + {% if plant.id == 8 %} +
    + {% endif %} +
    + + {% if plant.id == 8 %} +
    + Fatsia Japonica Image 1 +
    + {% endif %} +
    + +
    + {% if plant.id == 8 %} +
    + Fatsia Japonica Image 2 +
    + {% endif %} + + {% if plant.id == 8 %} +
    + Fatsia Japonica Image 3 +
    + {% endif %} +
    + + + {% if plant.id == 9 %} +
    + {% endif %} +
    + + {% if plant.id == 9 %} +
    + Hydrangea Macrophylla Image 1 +
    + {% endif %} +
    + +
    + {% if plant.id == 9 %} +
    + Hydrangea Macrophylla Image 2 +
    + {% endif %} + + {% if plant.id == 9 %} +
    + Hydrangea Macrophylla Image 3 +
    + {% endif %} +
    + + + {% if plant.id == 10 %} +
    + {% endif %} +
    + + {% if plant.id == 10 %} +
    + Alstroemeria Image 1 +
    + {% endif %} +
    + +
    + {% if plant.id == 10 %} +
    + Alstroemeria Image 2 +
    + {% endif %} + + {% if plant.id == 10 %} +
    + Alstroemeria Image 3 +
    + {% endif %} +
    + + +
    + + + +
    + +
    +

    {{ plant.plant_nickname }}

    +
    + + {% if plant.id == 5 %} +
    +

    {{ plant.species }}

    +
    + + {% elif plant.id == 6 %} +
    +

    {{ plant.species }}

    +
    + + {% elif plant.id == 9 %} +
    +

    {{ plant.species }}

    +
    + + {% else %} +
    +

    {{ plant.species }}

    +
    + {% endif %} + +
    + + + +
    +

    Price

    + £{{ plant.price }} +
    +

    Quantity

    + +
    + +
    + +
    +
    + + +
    + +
    + +

    Category

    + {% if plant.category_id == 1 %} +

    Indoor

    + {% else %} +

    Outdoor

    + {% endif %} +
    + +

    Size

    + {% if plant.size_id == 1 %} +

    Tiny

    + {% elif plant.size_id == 2 %} +

    Small

    + {% elif plant.size_id == 3 %} +

    Medium

    + {% else %} +

    Tall

    + {% endif %} +
    + +

    Type

    + {% if plant.plant_type_id == 1 %} +

    Cacti/Succulent

    + {% elif plant.plant_type_id == 2 %} +

    Hanging

    + {% elif plant.plant_type_id == 3 %} +

    Flowering

    + {% elif plant.plant_type_id == 4 %} +

    Palms

    + {% else %} +

    Ferns

    + {% endif %} +
    +
    + +
    +
    General Information:
    + {{ plant.general_info }}
    +
    Care Tips:
      +
    • {{ plant.care_tip1 }}
    • +
    • {{ plant.care_tip2 }}
    • +
    • {{ plant.care_tip3 }}
    • +
    +
    +
    + +
    +
    History of the Women in Tech Behind the Plant Nickname:
    + {{ plant.tech_description }}
    +
    +
    +
    + + + +{% endblock %} \ No newline at end of file diff --git a/application/templates/plant1.html b/application/templates/plant1.html new file mode 100644 index 0000000..8d9a175 --- /dev/null +++ b/application/templates/plant1.html @@ -0,0 +1,6 @@ +{% extends "layout.html" %} +{% block body_content %} +

    Plant 1

    +

    info about plant

    + +{% endblock %} \ No newline at end of file diff --git a/application/templates/plant10.html b/application/templates/plant10.html new file mode 100644 index 0000000..5f2c389 --- /dev/null +++ b/application/templates/plant10.html @@ -0,0 +1,6 @@ +{% extends "layout.html" %} +{% block body_content %} +

    Plant 10

    +

    info about plant

    + +{% endblock %} \ No newline at end of file diff --git a/application/templates/plant2.html b/application/templates/plant2.html new file mode 100644 index 0000000..0c8db8a --- /dev/null +++ b/application/templates/plant2.html @@ -0,0 +1,6 @@ +{% extends "layout.html" %} +{% block body_content %} +

    Plant 2

    +

    info about plant

    + +{% endblock %} \ No newline at end of file diff --git a/application/templates/plant3.html b/application/templates/plant3.html new file mode 100644 index 0000000..4f644c5 --- /dev/null +++ b/application/templates/plant3.html @@ -0,0 +1,6 @@ +{% extends "layout.html" %} +{% block body_content %} +

    Plant 3

    +

    info about plant

    + +{% endblock %} \ No newline at end of file diff --git a/application/templates/plant4.html b/application/templates/plant4.html new file mode 100644 index 0000000..757eef3 --- /dev/null +++ b/application/templates/plant4.html @@ -0,0 +1,6 @@ +{% extends "layout.html" %} +{% block body_content %} +

    Plant 4

    +

    info about plant

    + +{% endblock %} \ No newline at end of file diff --git a/application/templates/plant5.html b/application/templates/plant5.html new file mode 100644 index 0000000..696f30c --- /dev/null +++ b/application/templates/plant5.html @@ -0,0 +1,6 @@ +{% extends "layout.html" %} +{% block body_content %} +

    Plant 5

    +

    info about plant

    + +{% endblock %} \ No newline at end of file diff --git a/application/templates/plant6.html b/application/templates/plant6.html new file mode 100644 index 0000000..9333731 --- /dev/null +++ b/application/templates/plant6.html @@ -0,0 +1,6 @@ +{% extends "layout.html" %} +{% block body_content %} +

    Plant 6

    +

    info about plant

    + +{% endblock %} \ No newline at end of file diff --git a/application/templates/plant7.html b/application/templates/plant7.html new file mode 100644 index 0000000..4d8d318 --- /dev/null +++ b/application/templates/plant7.html @@ -0,0 +1,6 @@ +{% extends "layout.html" %} +{% block body_content %} +

    Plant 7

    +

    info about plant

    + +{% endblock %} \ No newline at end of file diff --git a/application/templates/plant8.html b/application/templates/plant8.html new file mode 100644 index 0000000..d812f3f --- /dev/null +++ b/application/templates/plant8.html @@ -0,0 +1,6 @@ +{% extends "layout.html" %} +{% block body_content %} +

    Plant 8

    +

    info about plant

    + +{% endblock %} \ No newline at end of file diff --git a/application/templates/plant9.html b/application/templates/plant9.html new file mode 100644 index 0000000..0416deb --- /dev/null +++ b/application/templates/plant9.html @@ -0,0 +1,6 @@ +{% extends "layout.html" %} +{% block body_content %} +

    Plant 9

    +

    info about plant

    + +{% endblock %} \ No newline at end of file diff --git a/application/templates/plant_care.html b/application/templates/plant_care.html new file mode 100644 index 0000000..5b735f1 --- /dev/null +++ b/application/templates/plant_care.html @@ -0,0 +1,70 @@ +{% extends "layout.html" %} +{% block body_content %} + +
    + spiky succulent +

    Plant Care Blog

    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Welcome to the Plant Care Blog! Here our staff will offer regular tips as well as highlighting important events.
    + + +{% for post in posts %} +
    +
    + {% if post.id == 1 %} + Card image cap + {% elif post.id == 2 %} + Card image cap + {% elif post.id == 3 %} + Card image cap + {% else %} + Card image cap + {% endif %} + + +
    +
    {{ post.title }}
    +
    Posted by: {{ post.author }}
    +

    {{ post.post_content }}

    +

    {{ post.date_posted.strftime('%B %d, %Y') }}

    +
    +
    + +
    + {% endfor %} +{% endblock %} \ No newline at end of file diff --git a/application/templates/plant_form.html b/application/templates/plant_form.html new file mode 100644 index 0000000..25df8ff --- /dev/null +++ b/application/templates/plant_form.html @@ -0,0 +1,44 @@ +{% extends "layout.html" %} +{% block body_content %} +
    +
    + {{ form.hidden_tag() }} +
    + Add Plant +
    Here, you'll be able to:
    +
  • Add a plant to the existing Plant Emporium Directory
  • +
    +
    + {{ form.plant_species.label(class="form-control-label") }} + {{ form.plant_species(class="form-control form-control-lg", placeholder="e.g. Boston Fern") }} +
    +
    + {{ form.plant_type.label(class="form-control-label") }} + {{ form.plant_type(class="form-control form-control-lg") }} +
    +
    + {{ form.plant_category.label(class="form-control-label") }} + {{ form.plant_category(class="form-control form-control-lg") }} +
    +
    + {{ form.plant_size.label(class="form-control-label") }} + {{ form.plant_size(class="form-control form-control-lg") }} +
    +
    + {{ form.plant_stock.label(class="form-control-label") }} + {{ form.plant_stock(class="form-control form-control-lg") }} +
    +
    + {{ form.plant_price.label(class="form-control-label") }} + {{ form.plant_price(class="form-control form-control-lg") }} +
    +
    +
    +
    + {{ form.submit(class="btn btn-secondary") }} +
    + +
    +
    + +{% endblock %} \ No newline at end of file diff --git a/application/templates/post.html b/application/templates/post.html new file mode 100644 index 0000000..d660531 --- /dev/null +++ b/application/templates/post.html @@ -0,0 +1,56 @@ +{% extends "layout.html" %} +{% block body_content %} + + +
    +
    +
    +
    + +

    {{ post.title }}

    + +
    +
    +
    +
    + + +
    +
    +
    +
    +

    + {{ post.post_content }} +

    +
    + + {% if post.id == 1 %} + plant + {% elif post.id == 2 %} + plant + {% elif post.id == 3 %} + plant + {% else %} + plant + {% endif %} + +
    +
    +
    +
    +
    + +
    + +
    + + Back to the Plant Care Blog +
    + + + + + +{% endblock %} \ No newline at end of file diff --git a/application/templates/register.html b/application/templates/register.html new file mode 100644 index 0000000..99f225a --- /dev/null +++ b/application/templates/register.html @@ -0,0 +1,93 @@ + + + +{% extends "layout.html" %} +{% block body_content %} +
    +
    + {{ form.hidden_tag() }} + {{ form.csrf_token() }} +
    + Join today +
    Here, you'll be able to:
    +
  • Order your favourite plants
  • +
  • Check in for hints on tips on caring for your new plants
  • +
  • Place orders
  • +
  • Track existing orders
  • +
    +
    Happy planting!
    +
    +
    + {{ form.first_name.label(class="form-control-label") }} + {{ form.first_name(class="form-control form-control-lg", placeholder="First name") }} +
    +
    + {{ form.last_name.label(class="form-control-label") }} + {{ form.last_name(class="form-control form-control-lg", placeholder="Last name") }} +
    +
    + {{ form.email.label(class="form-control-label") }} + {{ form.email(class="form-control form-control-lg", placeholder="example@example.com") }} +
      + {% for error in form.email.errors %} +
    • {{ error }}
    • + {% endfor %} +
    +
    +
    + {{ form.username.label(class="form-control-label") }} + {{ form.username(class="form-control form-control-lg", placeholder="Your username here") }} +
      + {% for error in form.username.errors %} +
    • {{ error }}
    • + {% endfor %} +
    +
    +
    + {{ form.password.label(class="form-control-label") }} + {{ form.password(class="form-control form-control-lg", placeholder="Password") }} +
    +
    + {{ form.confirm_password.label(class="form-control-label") }} + {{ form.confirm_password(class="form-control form-control-lg", placeholder="Repeat your password") }} +
      + {% for error in form.confirm_password.errors %} +
    • {{ error }}
    • + {% endfor %} +
    +
    +
    + {{ form.address_line_one.label(class="form-control-label") }} + {{ form.address_line_one(class="form-control form-control-lg", placeholder="Address line 1") }} +
    +
    + {{ form.address_line_two.label(class="form-control-label") }} + {{ form.address_line_two(class="form-control form-control-lg", placeholder="Address line 2") }} +
    +
    + {{ form.address_line_three.label(class="form-control-label") }} + {{ form.address_line_three(class="form-control form-control-lg", placeholder="Address line 3") }} +
    +
    + {{ form.postcode.label(class="form-control-label") }} + {{ form.postcode(class="form-control form-control-lg", placeholder="Postcode") }} +
    +
    + {{ form.phone_number.label(class="form-control-label") }} + {{ form.phone_number(class="form-control form-control-lg", placeholder="Enter your phone number") }} +
    +
    +
    + {{ form.submit(class="btn btn-secondary") }} +
    + +
    +
    + + Already Have An Account? Sign In + + +
    +
    + +{% endblock %} \ No newline at end of file diff --git a/application/templates/register_staff.html b/application/templates/register_staff.html new file mode 100644 index 0000000..66ec11b --- /dev/null +++ b/application/templates/register_staff.html @@ -0,0 +1,88 @@ +{% extends "layout.html" %} +{% block body_content %} +
    +
    + {{ form.hidden_tag() }} + {{ form.csrf_token() }} +
    + Staff Signup +
    Here, you'll be able to:
    +
  • Register a new member of staff to the Plant Emporium website
  • +
  • Provide access to our plant, customer and order tracking systems
  • +
    +
    + {{ form.first_name.label(class="form-control-label") }} + {{ form.first_name(class="form-control form-control-lg", placeholder="First name") }} +
    +
    + {{ form.last_name.label(class="form-control-label") }} + {{ form.last_name(class="form-control form-control-lg", placeholder="Last name") }} +
    +
    + {{ form.email.label(class="form-control-label") }} + {{ form.email(class="form-control form-control-lg", placeholder="example@plantemporium.com") }} +
      + {% for error in form.email.errors %} +
    • {{ error }}
    • + {% endfor %} +
    +
    +
    + {{ form.username.label(class="form-control-label") }} + {{ form.username(class="form-control form-control-lg", placeholder="Your username here") }} +
      + {% for error in form.username.errors %} +
    • {{ error }}
    • + {% endfor %} +
    +
    +
    + {{ form.password.label(class="form-control-label") }} + {{ form.password(class="form-control form-control-lg", placeholder="Password") }} +
    +
    + {{ form.confirm_password.label(class="form-control-label") }} + {{ form.confirm_password(class="form-control form-control-lg", placeholder="Repeat your password") }} +
      + {% for error in form.confirm_password.errors %} +
    • {{ error }}
    • + {% endfor %} +
    +
    +
    + {{ form.address_line_one.label(class="form-control-label") }} + {{ form.address_line_one(class="form-control form-control-lg", placeholder="Address line 1") }} +
    +
    + {{ form.address_line_two.label(class="form-control-label") }} + {{ form.address_line_two(class="form-control form-control-lg", placeholder="Address line 2") }} +
    +
    + {{ form.address_line_three.label(class="form-control-label") }} + {{ form.address_line_three(class="form-control form-control-lg", placeholder="Address line 3") }} +
    +
    + {{ form.postcode.label(class="form-control-label") }} + {{ form.postcode(class="form-control form-control-lg", placeholder="Postcode") }} +
    +
    + {{ form.phone_number.label(class="form-control-label") }} + {{ form.phone_number(class="form-control form-control-lg", placeholder="Enter your phone number") }} +
    +
    + {{ form.job_title.label(class="form-control-label") }} + {{ form.job_title(class="form-control form-control-lg", placeholder="Job role") }} +
    +
    + {{ form.date_of_birth.label(class="form-control-label") }} + {{ form.date_of_birth(class="form-control form-control-lg") }} +
    +
    +
    + {{ form.submit(class="btn btn-secondary") }} +
    + +
    +
    + +{% endblock %} \ No newline at end of file diff --git a/application/templates/search.html b/application/templates/search.html new file mode 100644 index 0000000..193d9da --- /dev/null +++ b/application/templates/search.html @@ -0,0 +1,13 @@ +{% extends "layout.html" %} +{% block body_content %} + +
    +

    You Searched For...

    + +

    {{ searched }}

    +
    +{% for post in posts %} + {{post.title}}
    +{% endfor %} + +{% endblock %} \ No newline at end of file diff --git a/application/templates/shop.html b/application/templates/shop.html new file mode 100644 index 0000000..f9cdf2e --- /dev/null +++ b/application/templates/shop.html @@ -0,0 +1,1191 @@ +{% extends "layout.html" %} + +{% block body_content %} + +
    + spiky succulent +

    Shop

    +
    + + +

    Shop

    + + +{% if session['logged_in_username'] %} +
    +

    Welcome {{ session['logged_in_username'] }}!

    +

    Are you logged in? That is {{ session['logged_in'] }}

    +

    What type of log in is it? You are logged in as {{ session['typesession'] }}

    + +

    Your Person ID is {{ session['id_number'] }}

    +
    +
    +{% else %} +
    +

    You are not currently logged in

    +

    Please Login to make a purchase

    + +
    +
    +{% endif %} + + +
    + + +
    + + +
    + + +
    + + +
    + + +
    + + + + +
    +
    + + + +
    +{% if plant_shop_plant %} +
    + + + + + + + + + + + + + + + {% for product, category, plant_type, size in plant_shop_plant %} + + {% if product.id == 1 %} + + {% endif %} + {% if product.id == 2 %} + + {% endif %} + {% if product.id == 3 %} + + {% endif %} + {% if product.id == 4 %} + + {% endif %} + {% if product.id == 5 %} + + {% endif %} + {% if product.id == 6 %} + + {% endif %} + {% if product.id == 7 %} + + {% endif %} + {% if product.id == 8 %} + + {% endif %} + {% if product.id == 9 %} + + {% endif %} + {% if product.id == 10 %} + + {% endif %} + + + + + + + + + + {% endfor %} + + + +
    ImagePlant NameSpeciesEnvironmentTypeSizePrice
    Boston Fern Image 1Aloe VeraParlour PalmAnthurium in a potSwiss Cheese PlantSweet Orange TreeClimbing RoseFatsia Japonica LeafWhite HydrangeaYellow Alstromeria{{ product.plant_nickname }}{{ product.species}}{{ category.category_description}}{{ plant_type.plant_type_description}}{{ size.size_description}}£{{ product.price }}
    +
    +
    +{% endif %} + + + +
    +{% if display_outdoor_plants %} +
    + + + + + + + + + + + + + + + {% for product, category, plant_type, size in display_outdoor_plants %} + + {% if product.id == 1 %} + + {% endif %} + {% if product.id == 2 %} + + {% endif %} + {% if product.id == 3 %} + + {% endif %} + {% if product.id == 4 %} + + {% endif %} + {% if product.id == 5 %} + + {% endif %} + {% if product.id == 6 %} + + {% endif %} + {% if product.id == 7 %} + + {% endif %} + {% if product.id == 8 %} + + {% endif %} + {% if product.id == 9 %} + + {% endif %} + {% if product.id == 10 %} + + {% endif %} + + + + + + + + + + {% endfor %} + + + +
    ImagePlant NameSpeciesEnvironmentTypeSizePrice
    Boston Fern Image 1Aloe VeraParlour PalmAnthurium in a potSwiss Cheese PlantSweet Orange TreeClimbing RoseFatsia Japonica LeafWhite HydrangeaYellow Alstromeria{{ product.plant_nickname }}{{ product.species}}{{ category.category_description}}{{ plant_type.plant_type_description}}{{ size.size_description}}£{{ product.price }}
    +
    +
    +{% endif %} + + + +
    +{% if display_indoor_plants %} +
    + + + + + + + + + + + + + + + {% for product, category, plant_type, size in display_indoor_plants %} + + {% if product.id == 1 %} + + {% endif %} + {% if product.id == 2 %} + + {% endif %} + {% if product.id == 3 %} + + {% endif %} + {% if product.id == 4 %} + + {% endif %} + {% if product.id == 5 %} + + {% endif %} + {% if product.id == 6 %} + + {% endif %} + {% if product.id == 7 %} + + {% endif %} + {% if product.id == 8 %} + + {% endif %} + {% if product.id == 9 %} + + {% endif %} + {% if product.id == 10 %} + + {% endif %} + + + + + + + + + + {% endfor %} + + + +
    ImagePlant NameSpeciesEnvironmentTypeSizePrice
    Boston Fern Image 1Aloe VeraParlour PalmAnthurium in a potSwiss Cheese PlantSweet Orange TreeClimbing RoseFatsia Japonica LeafWhite HydrangeaYellow Alstromeria{{ product.plant_nickname }}{{ product.species}}{{ category.category_description}}{{ plant_type.plant_type_description}}{{ size.size_description}}£{{ product.price }}
    +
    +
    +{% endif %} + + + +
    +{% if display_tiny_plants %} +
    + + + + + + + + + + + + + + + {% for product, category, plant_type, size in display_tiny_plants %} + + {% if product.id == 1 %} + + {% endif %} + {% if product.id == 2 %} + + {% endif %} + {% if product.id == 3 %} + + {% endif %} + {% if product.id == 4 %} + + {% endif %} + {% if product.id == 5 %} + + {% endif %} + {% if product.id == 6 %} + + {% endif %} + {% if product.id == 7 %} + + {% endif %} + {% if product.id == 8 %} + + {% endif %} + {% if product.id == 9 %} + + {% endif %} + {% if product.id == 10 %} + + {% endif %} + + + + + + + + + + {% endfor %} + + + +
    ImagePlant NameSpeciesEnvironmentTypeSizePrice
    Boston Fern Image 1Aloe VeraParlour PalmAnthurium in a potSwiss Cheese PlantSweet Orange TreeClimbing RoseFatsia Japonica LeafWhite HydrangeaYellow Alstromeria{{ product.plant_nickname }}{{ product.species}}{{ category.category_description}}{{ plant_type.plant_type_description}}{{ size.size_description}}£{{ product.price }}
    +
    +
    +{% endif %} + + +
    +{% if display_small_plants %} +
    + + + + + + + + + + + + + + + {% for product, category, plant_type, size in display_small_plants %} + + {% if product.id == 1 %} + + {% endif %} + {% if product.id == 2 %} + + {% endif %} + {% if product.id == 3 %} + + {% endif %} + {% if product.id == 4 %} + + {% endif %} + {% if product.id == 5 %} + + {% endif %} + {% if product.id == 6 %} + + {% endif %} + {% if product.id == 7 %} + + {% endif %} + {% if product.id == 8 %} + + {% endif %} + {% if product.id == 9 %} + + {% endif %} + {% if product.id == 10 %} + + {% endif %} + + + + + + + + + + {% endfor %} + + + +
    ImagePlant NameSpeciesEnvironmentTypeSizePrice
    Boston Fern Image 1Aloe VeraParlour PalmAnthurium in a potSwiss Cheese PlantSweet Orange TreeClimbing RoseFatsia Japonica LeafWhite HydrangeaYellow Alstromeria{{ product.plant_nickname }}{{ product.species}}{{ category.category_description}}{{ plant_type.plant_type_description}}{{ size.size_description}}£{{ product.price }}
    +
    +
    +{% endif %} + + + +
    +{% if display_medium_plants %} +
    + + + + + + + + + + + + + + + {% for product, category, plant_type, size in display_medium_plants %} + + {% if product.id == 1 %} + + {% endif %} + {% if product.id == 2 %} + + {% endif %} + {% if product.id == 3 %} + + {% endif %} + {% if product.id == 4 %} + + {% endif %} + {% if product.id == 5 %} + + {% endif %} + {% if product.id == 6 %} + + {% endif %} + {% if product.id == 7 %} + + {% endif %} + {% if product.id == 8 %} + + {% endif %} + {% if product.id == 9 %} + + {% endif %} + {% if product.id == 10 %} + + {% endif %} + + + + + + + + + + {% endfor %} + + + +
    ImagePlant NameSpeciesEnvironmentTypeSizePrice
    Boston Fern Image 1Aloe VeraParlour PalmAnthurium in a potSwiss Cheese PlantSweet Orange TreeClimbing RoseFatsia Japonica LeafWhite HydrangeaYellow Alstromeria{{ product.plant_nickname }}{{ product.species}}{{ category.category_description}}{{ plant_type.plant_type_description}}{{ size.size_description}}£{{ product.price }}
    +
    +
    +{% endif %} + + +
    +{% if display_tall_plants %} +
    + + + + + + + + + + + + + + + {% for product, category, plant_type, size in display_tall_plants %} + + {% if product.id == 1 %} + + {% endif %} + {% if product.id == 2 %} + + {% endif %} + {% if product.id == 3 %} + + {% endif %} + {% if product.id == 4 %} + + {% endif %} + {% if product.id == 5 %} + + {% endif %} + {% if product.id == 6 %} + + {% endif %} + {% if product.id == 7 %} + + {% endif %} + {% if product.id == 8 %} + + {% endif %} + {% if product.id == 9 %} + + {% endif %} + {% if product.id == 10 %} + + {% endif %} + + + + + + + + + + {% endfor %} + + + +
    ImagePlant NameSpeciesEnvironmentTypeSizePrice
    Boston Fern Image 1Aloe VeraParlour PalmAnthurium in a potSwiss Cheese PlantSweet Orange TreeClimbing RoseFatsia Japonica LeafWhite HydrangeaYellow Alstromeria{{ product.plant_nickname }}{{ product.species}}{{ category.category_description}}{{ plant_type.plant_type_description}}{{ size.size_description}}£{{ product.price }}
    +
    +
    +{% endif %} + + +
    +{% if display_cacti_succulent_plants %} +
    + + + + + + + + + + + + + + + {% for product, category, plant_type, size in display_cacti_succulent_plants %} + + {% if product.id == 1 %} + + {% endif %} + {% if product.id == 2 %} + + {% endif %} + {% if product.id == 3 %} + + {% endif %} + {% if product.id == 4 %} + + {% endif %} + {% if product.id == 5 %} + + {% endif %} + {% if product.id == 6 %} + + {% endif %} + {% if product.id == 7 %} + + {% endif %} + {% if product.id == 8 %} + + {% endif %} + {% if product.id == 9 %} + + {% endif %} + {% if product.id == 10 %} + + {% endif %} + + + + + + + + + + {% endfor %} + + + +
    ImagePlant NameSpeciesEnvironmentTypeSizePrice
    Boston Fern Image 1Aloe VeraParlour PalmAnthurium in a potSwiss Cheese PlantSweet Orange TreeClimbing RoseFatsia Japonica LeafWhite HydrangeaYellow Alstromeria{{ product.plant_nickname }}{{ product.species}}{{ category.category_description}}{{ plant_type.plant_type_description}}{{ size.size_description}}£{{ product.price }}
    +
    +
    +{% endif %} + + +
    +{% if display_hanging_plants %} +
    + + + + + + + + + + + + + + + {% for product, category, plant_type, size in display_hanging_plants %} + + {% if product.id == 1 %} + + {% endif %} + {% if product.id == 2 %} + + {% endif %} + {% if product.id == 3 %} + + {% endif %} + {% if product.id == 4 %} + + {% endif %} + {% if product.id == 5 %} + + {% endif %} + {% if product.id == 6 %} + + {% endif %} + {% if product.id == 7 %} + + {% endif %} + {% if product.id == 8 %} + + {% endif %} + {% if product.id == 9 %} + + {% endif %} + {% if product.id == 10 %} + + {% endif %} + + + + + + + + + + {% endfor %} + + + +
    ImagePlant NameSpeciesEnvironmentTypeSizePrice
    Boston Fern Image 1Aloe VeraParlour PalmAnthurium in a potSwiss Cheese PlantSweet Orange TreeClimbing RoseFatsia Japonica LeafWhite HydrangeaYellow Alstromeria{{ product.plant_nickname }}{{ product.species}}{{ category.category_description}}{{ plant_type.plant_type_description}}{{ size.size_description}}£{{ product.price }}
    +
    +
    +{% endif %} + + +
    +{% if display_flowering_plants %} +
    + + + + + + + + + + + + + + + {% for product, category, plant_type, size in display_flowering_plants %} + + {% if product.id == 1 %} + + {% endif %} + {% if product.id == 2 %} + + {% endif %} + {% if product.id == 3 %} + + {% endif %} + {% if product.id == 4 %} + + {% endif %} + {% if product.id == 5 %} + + {% endif %} + {% if product.id == 6 %} + + {% endif %} + {% if product.id == 7 %} + + {% endif %} + {% if product.id == 8 %} + + {% endif %} + {% if product.id == 9 %} + + {% endif %} + {% if product.id == 10 %} + + {% endif %} + + + + + + + + + + {% endfor %} + + + +
    ImagePlant NameSpeciesEnvironmentTypeSizePrice
    Boston Fern Image 1Aloe VeraParlour PalmAnthurium in a potSwiss Cheese PlantSweet Orange TreeClimbing RoseFatsia Japonica LeafWhite HydrangeaYellow Alstromeria{{ product.plant_nickname }}{{ product.species}}{{ category.category_description}}{{ plant_type.plant_type_description}}{{ size.size_description}}£{{ product.price }}
    +
    +
    +{% endif %} + + +
    +{% if display_palm_plants %} +
    + + + + + + + + + + + + + + + {% for product, category, plant_type, size in display_palm_plants %} + + {% if product.id == 1 %} + + {% endif %} + {% if product.id == 2 %} + + {% endif %} + {% if product.id == 3 %} + + {% endif %} + {% if product.id == 4 %} + + {% endif %} + {% if product.id == 5 %} + + {% endif %} + {% if product.id == 6 %} + + {% endif %} + {% if product.id == 7 %} + + {% endif %} + {% if product.id == 8 %} + + {% endif %} + {% if product.id == 9 %} + + {% endif %} + {% if product.id == 10 %} + + {% endif %} + + + + + + + + + + {% endfor %} + + + +
    ImagePlant NameSpeciesEnvironmentTypeSizePrice
    Boston Fern Image 1Aloe VeraParlour PalmAnthurium in a potSwiss Cheese PlantSweet Orange TreeClimbing RoseFatsia Japonica LeafWhite HydrangeaYellow Alstromeria{{ product.plant_nickname }}{{ product.species}}{{ category.category_description}}{{ plant_type.plant_type_description}}{{ size.size_description}}£{{ product.price }}
    +
    +
    +{% endif %} + + +
    + +{% if display_fern_plants %} +
    + + + + + + + + + + + + + + + {% for product, category, plant_type, size in display_fern_plants %} + + {% if product.id == 1 %} + + {% endif %} + {% if product.id == 2 %} + + {% endif %} + {% if product.id == 3 %} + + {% endif %} + {% if product.id == 4 %} + + {% endif %} + {% if product.id == 5 %} + + {% endif %} + {% if product.id == 6 %} + + {% endif %} + {% if product.id == 7 %} + + {% endif %} + {% if product.id == 8 %} + + {% endif %} + {% if product.id == 9 %} + + {% endif %} + {% if product.id == 10 %} + + {% endif %} + + + + + + + + + + {% endfor %} + + + +
    ImagePlant NameSpeciesEnvironmentTypeSizePrice
    Boston Fern Image 1Aloe VeraParlour PalmAnthurium in a potSwiss Cheese PlantSweet Orange TreeClimbing RoseFatsia Japonica LeafWhite HydrangeaYellow Alstromeria{{ product.plant_nickname }}{{ product.species}}{{ category.category_description}}{{ plant_type.plant_type_description}}{{ size.size_description}}£{{ product.price }}
    +
    +
    +{% endif %} + + + +
    + +{% if display_value_saver %} +
    + + + + + + + + + + + + + + + {% for product, category, plant_type, size in display_value_saver %} + + {% if product.id == 1 %} + + {% endif %} + {% if product.id == 2 %} + + {% endif %} + {% if product.id == 3 %} + + {% endif %} + {% if product.id == 4 %} + + {% endif %} + {% if product.id == 5 %} + + {% endif %} + {% if product.id == 6 %} + + {% endif %} + {% if product.id == 7 %} + + {% endif %} + {% if product.id == 8 %} + + {% endif %} + {% if product.id == 9 %} + + {% endif %} + {% if product.id == 10 %} + + {% endif %} + + + + + + + + + + {% endfor %} + + + +
    ImagePlant NameSpeciesEnvironmentTypeSizePrice
    Boston Fern Image 1Aloe VeraParlour PalmAnthurium in a potSwiss Cheese PlantSweet Orange TreeClimbing RoseFatsia Japonica LeafWhite HydrangeaYellow Alstromeria{{ product.plant_nickname }}{{ product.species}}{{ category.category_description}}{{ plant_type.plant_type_description}}{{ size.size_description}}£{{ product.price }}
    +
    +
    +{% endif %} + + +
    + +{% if display_modest_picks %} +
    + + + + + + + + + + + + + + + {% for product, category, plant_type, size in display_modest_picks %} + + {% if product.id == 1 %} + + {% endif %} + {% if product.id == 2 %} + + {% endif %} + {% if product.id == 3 %} + + {% endif %} + {% if product.id == 4 %} + + {% endif %} + {% if product.id == 5 %} + + {% endif %} + {% if product.id == 6 %} + + {% endif %} + {% if product.id == 7 %} + + {% endif %} + {% if product.id == 8 %} + + {% endif %} + {% if product.id == 9 %} + + {% endif %} + {% if product.id == 10 %} + + {% endif %} + + + + + + + + + + {% endfor %} + + + +
    ImagePlant NameSpeciesEnvironmentTypeSizePrice
    Boston Fern Image 1Aloe VeraParlour PalmAnthurium in a potSwiss Cheese PlantSweet Orange TreeClimbing RoseFatsia Japonica LeafWhite HydrangeaYellow Alstromeria{{ product.plant_nickname }}{{ product.species}}{{ category.category_description}}{{ plant_type.plant_type_description}}{{ size.size_description}}£{{ product.price }}
    +
    +
    +{% endif %} + + + +
    + +{% if display_fancy_picks %} +
    + + + + + + + + + + + + + + + {% for product, category, plant_type, size in display_fancy_picks %} + + {% if product.id == 1 %} + + {% endif %} + {% if product.id == 2 %} + + {% endif %} + {% if product.id == 3 %} + + {% endif %} + {% if product.id == 4 %} + + {% endif %} + {% if product.id == 5 %} + + {% endif %} + {% if product.id == 6 %} + + {% endif %} + {% if product.id == 7 %} + + {% endif %} + {% if product.id == 8 %} + + {% endif %} + {% if product.id == 9 %} + + {% endif %} + {% if product.id == 10 %} + + {% endif %} + + + + + + + + + + {% endfor %} + + + +
    ImagePlant NameSpeciesEnvironmentTypeSizePrice
    Boston Fern Image 1Aloe VeraParlour PalmAnthurium in a potSwiss Cheese PlantSweet Orange TreeClimbing RoseFatsia Japonica LeafWhite HydrangeaYellow Alstromeria{{ product.plant_nickname }}{{ product.species}}{{ category.category_description}}{{ plant_type.plant_type_description}}{{ size.size_description}}£{{ product.price }}
    +
    +
    +{% endif %} + + + +
    + +{% if display_premium_range %} +
    + + + + + + + + + + + + + + + {% for product, category, plant_type, size in display_premium_range %} + + {% if product.id == 1 %} + + {% endif %} + {% if product.id == 2 %} + + {% endif %} + {% if product.id == 3 %} + + {% endif %} + {% if product.id == 4 %} + + {% endif %} + {% if product.id == 5 %} + + {% endif %} + {% if product.id == 6 %} + + {% endif %} + {% if product.id == 7 %} + + {% endif %} + {% if product.id == 8 %} + + {% endif %} + {% if product.id == 9 %} + + {% endif %} + {% if product.id == 10 %} + + {% endif %} + + + + + + + + + + {% endfor %} + + + +
    ImagePlant NameSpeciesEnvironmentTypeSizePrice
    Boston Fern Image 1Aloe VeraParlour PalmAnthurium in a potSwiss Cheese PlantSweet Orange TreeClimbing RoseFatsia Japonica LeafWhite HydrangeaYellow Alstromeria{{ product.plant_nickname }}{{ product.species}}{{ category.category_description}}{{ plant_type.plant_type_description}}{{ size.size_description}}£{{ product.price }}
    +
    +
    +{% endif %} + +{% endblock %} \ No newline at end of file diff --git a/application/templates/staff_deletion.html b/application/templates/staff_deletion.html new file mode 100644 index 0000000..585673a --- /dev/null +++ b/application/templates/staff_deletion.html @@ -0,0 +1,12 @@ +{% extends "layout.html" %} +{% block body_content %} + Staff List + + +
    +{% for staff in staff %} +

    {{staff.id}} {{staff.first_name}} {{staff.last_name}} {{staff.email}}

    +{% endfor %} +
    + {{ message }} +
    \ No newline at end of file diff --git a/application/templates/staff_jobs.html b/application/templates/staff_jobs.html new file mode 100644 index 0000000..8adc72f --- /dev/null +++ b/application/templates/staff_jobs.html @@ -0,0 +1,38 @@ +{% extends "layout.html" %} +{% block body_content %} + + + +
    +

    Staff List

    + +
    +
    + + + + {% for header in headings %} + + {% endfor %} + + + + + {% for job, staff in staff_and_jobs %} + + + + + + + + {% endfor %} + + +
    {{ header }}
    {{job.job_title}}{{staff.first_name}} {{staff.last_name}}{{ staff.email }}
    +
    + +
    + +
    +{% endblock %} \ No newline at end of file diff --git a/application/templates/staff_list.html b/application/templates/staff_list.html new file mode 100644 index 0000000..998b64f --- /dev/null +++ b/application/templates/staff_list.html @@ -0,0 +1,15 @@ +{% extends "layout.html" %} +{% block body_content %} + Staff List + + +
    +{% for staff in staff %} +

    {{staff.id}} {{staff.first_name}} {{staff.last_name}} {{staff.email}}

    +{% endfor %} +
    + {{ message }} +
    + + +{% endblock %} \ No newline at end of file diff --git a/application/templates/stock_list.html b/application/templates/stock_list.html new file mode 100644 index 0000000..6e5272b --- /dev/null +++ b/application/templates/stock_list.html @@ -0,0 +1,54 @@ +{% extends "layout.html" %} +{% block body_content %} + Outstanding Orders + + +
    + +

    + +
    + {{ message }} +
    + + + + +
    +

    Current stock list

    + +
    +
    + + + + {% for header in headings %} + + {% endfor %} + + + + + {% for product, category, plant_type, size in plant_shop_plant %} + + + + + + + + + + + + + {% endfor %} + + +
    {{ header }}
    {{product.species}} {{category.category_description}} {{size.size_description}} {{plant_type.plant_type_description}}{{product.price}}{{product.stock}}
    +
    + +
    + +
    +{% endblock %} \ No newline at end of file diff --git a/application/templates/unused.html b/application/templates/unused.html new file mode 100644 index 0000000..0c33165 --- /dev/null +++ b/application/templates/unused.html @@ -0,0 +1,15 @@ + + + +
    +
    + + {{ form.hidden_tag() }} + {{ form.first_name.label }} {{ form.first_name }} +
    + {{ form.last_name.label }} {{ form.last_name }} +
    + {{ form.submit }} + {{ message }} +
    +
    \ No newline at end of file diff --git a/application/templates/update_email.html b/application/templates/update_email.html new file mode 100644 index 0000000..fd1e06a --- /dev/null +++ b/application/templates/update_email.html @@ -0,0 +1,24 @@ +{% extends "layout.html" %} +{% block body_content %} + + +
    +
    + {{ form.hidden_tag() }} + {{ form.csrf_token() }} +
    +
    + {{ form.new_email.label(class="form-control-label") }} + {{ form.new_email(class="form-control form-control-lg", placeholder="Example@email.com") }} +
    +
    +
    + {{ form.submit(class="btn btn-secondary") }} +
    +
    + +
    + + + +{% endblock %} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index fef56cc..5cdc57c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,6 @@ flask-sqlalchemy pymysql wtforms flask_wtf -markupsafe==2.0.1 \ No newline at end of file +markupsafe==2.0.1 +cryptography +email_validator diff --git a/test.txt b/test.txt new file mode 100644 index 0000000..65cca1c --- /dev/null +++ b/test.txt @@ -0,0 +1 @@ +testing my fork \ No newline at end of file