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, Document, Amenities from datetime import datetime from utils import generate_password, send_email, save_document @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) @app.route('/') def home(): page = request.args.get('page', 1, type=int) per_page = 10 property_type = request.args.get('property_type') query = Listing.query if property_type: query = query.filter_by(property_type=property_type) listings = query.paginate(page=page, per_page=per_page) return render_template('index.html', listings=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('upload_document')) return render_template('login.html') @app.route('/logout/') @login_required def logout(): logout_user() return redirect(url_for('login')) @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'POST': email = request.form['email'] password_plain = generate_password() password = bcrypt.generate_password_hash(password_plain).decode('utf-8') phone = request.form['phone'] user = User(email=email, password=password, phone=phone) db.session.add(user) db.session.commit() send_email(email, 'Your Account Password', f'Your password is: {password_plain}') login_user(user) return redirect(url_for('upload_document')) return render_template('register.html') @app.route('/upload-document', methods=['GET', 'POST']) @login_required def upload_document(): document = Document.query.filter_by(user_id=current_user.id).first() if document: if not document.verified: return render_template('upload_document.html', message="Your document is under verification.") return redirect(url_for('dashboard')) if request.method == 'POST': file = request.files['document'] if not file: return render_template('upload_document.html', message="No file selected.") try: saved_filename = save_document(file, 'documents') new_document = Document(filename=saved_filename, user_id=current_user.id) db.session.add(new_document) db.session.commit() return redirect(url_for('upload_document')) except ValueError as e: return render_template('upload_document.html', message=str(e)) return render_template('upload_document.html', message=None) @app.route('/verify-document/', methods=['POST']) @login_required def verify_document(document_id): if current_user.is_host: document = Document.query.get_or_404(document_id) document.verified = True db.session.commit() return redirect(url_for('dashboard')) return redirect(url_for('home')) @app.route('/dashboard', methods=['GET', 'POST']) @login_required def dashboard(): if current_user.is_host: listings = Listing.query.filter_by(host_id=current_user.id).all() users = User.query.all() documents = {doc.user_id: doc for doc in Document.query.all()} return render_template('dashboard.html', listings=listings, users=users, documents=documents) return redirect(url_for('home')) @app.route('/create-listing', methods=['GET', 'POST']) @login_required def create_listing(): if not current_user.is_host: return redirect(url_for('home')) amenities_list = Amenities.query.all() 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') guests = request.form['guests'] rooms = request.form['rooms'] beds = request.form['beds'] bathrooms = request.form['bathrooms'] selected_amenities = request.form.getlist('amenities') listing = Listing(title=title, description=description, price=price, location=location, property_type=property_type, host_id=current_user.id, latitude=latitude, longitude=longitude, guests=guests, rooms=rooms, beds=beds, bathrooms=bathrooms) for amenity_id in selected_amenities: amenity = Amenities.query.get(int(amenity_id)) if amenity: listing.amenities.append(amenity) 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', property_types=Listing.PROPERTY_TYPES, amenities_list=amenities_list) @app.route('/edit-listing/', methods=['GET', 'POST']) @login_required def edit_listing(listing_id): listing = Listing.query.get_or_404(listing_id) if listing.host_id != current_user.id: return redirect(url_for('dashboard')) amenities_list = Amenities.query.all() selected_amenities = [amenity.id for amenity in listing.amenities] 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') guests = request.form['guests'] rooms = request.form['rooms'] beds = request.form['beds'] bathrooms = request.form['bathrooms'] selected_amenities_ids = request.form.getlist('amenities') listing.title = title listing.description = description listing.price = price listing.location = location listing.property_type = property_type listing.latitude = latitude listing.longitude = longitude listing.guests = guests listing.rooms = rooms listing.beds = beds listing.bathrooms = bathrooms listing.amenities = [] for amenity_id in selected_amenities_ids: amenity = Amenities.query.get(int(amenity_id)) if amenity: listing.amenities.append(amenity) db.session.commit() return redirect(url_for('dashboard')) return render_template('edit_listing.html', listing=listing, amenities_list=amenities_list, selected_amenities=selected_amenities) @app.route('/booking/', methods=['GET', 'POST']) @login_required def booking(listing_id): listing = Listing.query.get_or_404(listing_id) booked_dates = Booking.query.filter_by(listing_id=listing_id).all() unavailable_dates = [(booking.check_in.strftime('%Y-%m-%d'), booking.check_out.strftime('%Y-%m-%d')) for booking in booked_dates] if request.method == 'POST': check_in = datetime.strptime(request.form['check_in'], '%Y-%m-%d') check_out = datetime.strptime(request.form['check_out'], '%Y-%m-%d') for start_date, end_date in unavailable_dates: if (check_in.strftime('%Y-%m-%d') >= start_date and check_in.strftime('%Y-%m-%d') <= end_date) or \ (check_out.strftime('%Y-%m-%d') >= start_date and check_out.strftime('%Y-%m-%d') <= end_date): return render_template('booking.html', listing=listing, unavailable_dates=unavailable_dates, error="Selected dates are not available.") try: check_in = datetime.strptime(request.form['check_in'], '%Y-%m-%d') check_out = datetime.strptime(request.form['check_out'], '%Y-%m-%d') if check_out <= check_in: return render_template('booking.html', listing=listing, unavailable_dates=unavailable_dates, error="Check-out date must be after check-in date.") guests = int(request.form['guests']) if guests > listing.guests: return render_template('booking.html', listing=listing, unavailable_dates=unavailable_dates, error="Number of guests exceeds maximum allowed.") booking = Booking(user_id=current_user.id, 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')) except ValueError: return render_template('booking.html', listing=listing, unavailable_dates=unavailable_dates, error="Invalid date format.") return render_template('booking.html', listing=listing, unavailable_dates=unavailable_dates) @app.route('/view/', methods=['GET']) def view_listing(listing_id): listing = Listing.query.get_or_404(listing_id) property_type_display = Listing.PROPERTY_TYPES.get(listing.property_type, 'Unknown') amenities = list(listing.amenities) return render_template('view.html', listing=listing, property_type_display=property_type_display, amenities=amenities)