From 71b54bae9431b14ebf23b8e60fd412fa7c47e372 Mon Sep 17 00:00:00 2001 From: 3err0 Date: Sat, 4 Jan 2025 19:57:22 +0800 Subject: [PATCH] firrst commit --- app.py | 19 +++++++ models.py | 36 ++++++++++++++ routes.py | 94 +++++++++++++++++++++++++++++++++++ templates/base.html | 34 +++++++++++++ templates/booking.html | 37 ++++++++++++++ templates/create_listing.html | 40 +++++++++++++++ templates/dashboard.html | 20 ++++++++ templates/index.html | 19 +++++++ templates/login.html | 20 ++++++++ templates/register.html | 24 +++++++++ 10 files changed, 343 insertions(+) create mode 100644 app.py create mode 100644 models.py create mode 100644 routes.py create mode 100644 templates/base.html create mode 100644 templates/booking.html create mode 100644 templates/create_listing.html create mode 100644 templates/dashboard.html create mode 100644 templates/index.html create mode 100644 templates/login.html create mode 100644 templates/register.html diff --git a/app.py b/app.py new file mode 100644 index 0000000..3b27d17 --- /dev/null +++ b/app.py @@ -0,0 +1,19 @@ +from flask import Flask +from flask_sqlalchemy import SQLAlchemy +from flask_bcrypt import Bcrypt +from flask_login import LoginManager + +app = Flask(__name__) +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db' +app.config['SECRET_KEY'] = 'supersecretkey' + +db = SQLAlchemy(app) +bcrypt = Bcrypt(app) +login_manager = LoginManager(app) +login_manager.login_view = 'login' + +from routes import * +from models import * + +if __name__ == '__main__': + app.run(debug=True) diff --git a/models.py b/models.py new file mode 100644 index 0000000..59aa1ee --- /dev/null +++ b/models.py @@ -0,0 +1,36 @@ +from app import db +from flask_login import UserMixin + +class User(db.Model, UserMixin): + id = db.Column(db.Integer, primary_key=True) + email = db.Column(db.String(150), unique=True, nullable=False) + password = db.Column(db.String(60), nullable=False) + phone = db.Column(db.String(20), nullable=False) + is_host = db.Column(db.Boolean, default=False) + +class Listing(db.Model): + id = db.Column(db.Integer, primary_key=True) + title = db.Column(db.String(150), nullable=False) + description = db.Column(db.Text, nullable=False) + price = db.Column(db.Float, nullable=False) + location = db.Column(db.String(150), nullable=False) + property_type = db.Column(db.String(50), nullable=False) + host_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) + images = db.relationship('Image', backref='listing', lazy=True) + latitude = db.Column(db.Float, nullable=True) + longitude = db.Column(db.Float, nullable=True) + +class Image(db.Model): + id = db.Column(db.Integer, primary_key=True) + url = db.Column(db.String(300), nullable=False) + listing_id = db.Column(db.Integer, db.ForeignKey('listing.id'), nullable=False) + +class Booking(db.Model): + id = db.Column(db.Integer, primary_key=True) + guest_name = db.Column(db.String(100), nullable=False) + email = db.Column(db.String(120), nullable=False) + phone = db.Column(db.String(20), nullable=False) + listing_id = db.Column(db.Integer, db.ForeignKey('listing.id'), nullable=False) + check_in = db.Column(db.DateTime, nullable=False) + check_out = db.Column(db.DateTime, nullable=False) + guests = db.Column(db.Integer, nullable=False) \ No newline at end of file diff --git a/routes.py b/routes.py new file mode 100644 index 0000000..cd16d65 --- /dev/null +++ b/routes.py @@ -0,0 +1,94 @@ +from flask import render_template, request, redirect, url_for +from flask_login import login_user, login_required, logout_user, current_user +from app import app, db, bcrypt, login_manager +from models import User, Listing, Booking, Image +from datetime import datetime + +@login_manager.user_loader +def load_user(user_id): + return User.query.get(int(user_id)) + +@app.route('/') +def home(): + property_type = request.args.get('property_type') + listings = Listing.query + available_listings = [] + for listing in listings: + bookings = Booking.query.filter_by(listing_id=listing.id).all() + if all(datetime.strptime(booking.check_out, '%Y-%m-%d') < datetime.now() for booking in bookings): + available_listings.append(listing) + if property_type: + available_listings = [l for l in available_listings if l.property_type == property_type] + return render_template('index.html', listings=available_listings) + +@app.route('/login', methods=['GET', 'POST']) +def login(): + if request.method == 'POST': + email = request.form['email'] + password = request.form['password'] + user = User.query.filter_by(email=email).first() + if user and bcrypt.check_password_hash(user.password, password): + login_user(user) + return redirect(url_for('dashboard')) + return render_template('login.html') + +@app.route('/register', methods=['GET', 'POST']) +def register(): + if request.method == 'POST': + email = request.form['email'] + password = bcrypt.generate_password_hash(request.form['password']).decode('utf-8') + phone = request.form['phone'] + user = User(email=email, password=password, phone=phone) + db.session.add(user) + db.session.commit() + login_user(user) + return redirect(url_for('dashboard')) + return render_template('register.html') + +@app.route('/dashboard') +@login_required +def dashboard(): + if current_user.is_host: + listings = Listing.query.filter_by(host_id=current_user.id).all() + return render_template('dashboard.html', listings=listings) + return redirect(url_for('home')) + +@app.route('/create-listing', methods=['GET', 'POST']) +@login_required +def create_listing(): + if request.method == 'POST': + title = request.form['title'] + description = request.form['description'] + price = request.form['price'] + location = request.form['location'] + property_type = request.form['property_type'] + latitude = request.form.get('latitude') + longitude = request.form.get('longitude') + listing = Listing(title=title, description=description, price=price, location=location, property_type=property_type, host_id=current_user.id, latitude=latitude, longitude=longitude) + db.session.add(listing) + db.session.flush() + + image_urls = request.form.getlist('images') + for url in image_urls: + image = Image(url=url, listing_id=listing.id) + db.session.add(image) + + db.session.commit() + return redirect(url_for('dashboard')) + return render_template('create_listing.html') + +@app.route('/booking/', methods=['GET', 'POST']) +def booking(listing_id): + listing = Listing.query.get_or_404(listing_id) + if request.method == 'POST': + guest_name = request.form['name'] + email = request.form['email'] + phone = request.form['phone'] + check_in = datetime.strptime(request.form['check_in'], '%Y-%m-%d') + check_out = datetime.strptime(request.form['check_out'], '%Y-%m-%d') + guests = request.form['guests'] + booking = Booking(guest_name=guest_name, email=email, phone=phone, listing_id=listing_id, check_in=check_in, check_out=check_out, guests=guests) + db.session.add(booking) + db.session.commit() + return redirect(url_for('home')) + return render_template('booking.html', listing=listing) \ No newline at end of file diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..f8d608c --- /dev/null +++ b/templates/base.html @@ -0,0 +1,34 @@ + + + + + + {% block title %}Booking System{% endblock %} + + + + +
+ {% block content %}{% endblock %} +
+ + + \ No newline at end of file diff --git a/templates/booking.html b/templates/booking.html new file mode 100644 index 0000000..a800510 --- /dev/null +++ b/templates/booking.html @@ -0,0 +1,37 @@ +{% extends 'base.html' %} +{% block title %}Booking{% endblock %} + +{% block content %} +
+
+

Book {{ listing.title }}

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+{% endblock %} diff --git a/templates/create_listing.html b/templates/create_listing.html new file mode 100644 index 0000000..8f2dcae --- /dev/null +++ b/templates/create_listing.html @@ -0,0 +1,40 @@ +{% extends 'base.html' %} +{% block title %}Create Listing{% endblock %} +{% block content %} +
+
+

Create Listing

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+{% endblock %} diff --git a/templates/dashboard.html b/templates/dashboard.html new file mode 100644 index 0000000..ae34c26 --- /dev/null +++ b/templates/dashboard.html @@ -0,0 +1,20 @@ +{% extends 'base.html' %} +{% block title %}Dashboard{% endblock %} +{% block content %} +

Your Listings

+
+ {% for listing in listings %} +
+
+ ... +
+
{{ listing.title }}
+

{{ listing.description }}

+ Edit + Delete +
+
+
+ {% endfor %} +
+{% endblock %} \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..b8abfb7 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,19 @@ +{% extends 'base.html' %} +{% block title %}Home{% endblock %} +{% block content %} +

Available Listings

+
+ {% for listing in listings %} +
+
+ ... +
+
{{ listing.title }}
+

{{ listing.description }}

+ Book Now +
+
+
+ {% endfor %} +
+{% endblock %} \ No newline at end of file diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 0000000..5db1deb --- /dev/null +++ b/templates/login.html @@ -0,0 +1,20 @@ +{% extends 'base.html' %} +{% block title %}Login{% endblock %} +{% block content %} +
+
+

Login

+
+
+ + +
+
+ + +
+ +
+
+
+{% endblock %} \ No newline at end of file diff --git a/templates/register.html b/templates/register.html new file mode 100644 index 0000000..689fae9 --- /dev/null +++ b/templates/register.html @@ -0,0 +1,24 @@ +{% extends 'base.html' %} +{% block title %}Register{% endblock %} +{% block content %} +
+
+

Register

+
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+{% endblock %} \ No newline at end of file