{{ post.author.nickname }}
+{{ post.created_at.strftime('%b %d, %Y') }}
++ + {{ post.title }} + +
+ + {% if post.subtitle %} +{{ post.subtitle }}
+ {% endif %} + ++ {{ post.content[:120] }}{% if post.content|length > 120 %}...{% endif %} +
+ +diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..e69de29
diff --git a/.gitignore b/.gitignore
index e69de29..8578775 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1,121 @@
+# Python
+__pycache__/
+*.py[cod]
+*$py.class
+*.so
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# pyenv
+.python-version
+
+# celery beat schedule file
+celerybeat-schedule
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# IDE
+.vscode/
+.idea/
+*.swp
+*.swo
+*~
+
+# OS
+.DS_Store
+.DS_Store?
+._*
+.Spotlight-V100
+.Trashes
+ehthumbs.db
+Thumbs.db
+
+# Application specific
+uploads/
+*.db
+*.sqlite
\ No newline at end of file
diff --git a/app/__init__.py b/app/__init__.py
index bda8bb1..4e479e2 100644
--- a/app/__init__.py
+++ b/app/__init__.py
@@ -1,16 +1,8 @@
from flask import Flask
-from flask_sqlalchemy import SQLAlchemy
-from flask_migrate import Migrate
-from flask_login import LoginManager
-from flask_mail import Mail
+from app.extensions import db, migrate, login_manager, mail
from config import config
import os
-db = SQLAlchemy()
-migrate = Migrate()
-login_manager = LoginManager()
-mail = Mail()
-
def create_app(config_name=None):
app = Flask(__name__)
@@ -53,8 +45,3 @@ def create_app(config_name=None):
os.makedirs(os.path.join(upload_dir, 'gpx'), exist_ok=True)
return app
-
-@login_manager.user_loader
-def load_user(user_id):
- from app.models import User
- return User.query.get(int(user_id))
diff --git a/app/extensions.py b/app/extensions.py
new file mode 100644
index 0000000..894167d
--- /dev/null
+++ b/app/extensions.py
@@ -0,0 +1,10 @@
+from flask_sqlalchemy import SQLAlchemy
+from flask_migrate import Migrate
+from flask_login import LoginManager
+from flask_mail import Mail
+
+# Initialize extensions
+db = SQLAlchemy()
+migrate = Migrate()
+login_manager = LoginManager()
+mail = Mail()
diff --git a/app/models.py b/app/models.py
index 7ed355b..0c52891 100644
--- a/app/models.py
+++ b/app/models.py
@@ -1,9 +1,7 @@
from datetime import datetime
-from flask_sqlalchemy import SQLAlchemy
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash
-
-db = SQLAlchemy()
+from app.extensions import db
class User(UserMixin, db.Model):
__tablename__ = 'users'
@@ -70,7 +68,8 @@ class PostImage(db.Model):
original_name = db.Column(db.String(255), nullable=False)
description = db.Column(db.Text)
size = db.Column(db.Integer, nullable=False)
- mime_type = db.Column(db.String(100), nullable=False)
+ mime_type = db.Column(db.String(100), default='image/jpeg', nullable=False)
+ is_cover = db.Column(db.Boolean, default=False, nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
# Foreign Keys
diff --git a/app/routes/auth.py b/app/routes/auth.py
index 0daa5ed..f981e1f 100644
--- a/app/routes/auth.py
+++ b/app/routes/auth.py
@@ -61,8 +61,9 @@ def register():
try:
db.session.add(user)
db.session.commit()
- flash('Registration successful! You can now log in.', 'success')
- return redirect(url_for('auth.login'))
+ login_user(user)
+ flash('Registration successful! Welcome to the community!', 'success')
+ return redirect(url_for('community.index'))
except Exception as e:
db.session.rollback()
flash('An error occurred during registration. Please try again.', 'error')
diff --git a/app/routes/community.py b/app/routes/community.py
index 27c3dfe..0ad9b69 100644
--- a/app/routes/community.py
+++ b/app/routes/community.py
@@ -1,6 +1,7 @@
from flask import Blueprint, render_template, request, redirect, url_for, flash, current_app, jsonify
from flask_login import login_required, current_user
-from app.models import Post, PostImage, GPXFile, User, Comment, Like, db
+from app.models import Post, PostImage, GPXFile, User, Comment, Like
+from app.extensions import db
from app.forms import PostForm, CommentForm
from werkzeug.utils import secure_filename
from werkzeug.exceptions import RequestEntityTooLarge
@@ -14,12 +15,16 @@ community = Blueprint('community', __name__)
@community.route('/')
def index():
- """Community posts listing page"""
+ """Community main page with map and posts"""
page = request.args.get('page', 1, type=int)
posts = Post.query.filter_by(published=True).order_by(Post.created_at.desc()).paginate(
- page=page, per_page=10, error_out=False
+ page=page, per_page=12, error_out=False
)
- return render_template('community/index.html', posts=posts)
+
+ # Get posts with GPX files for map display
+ posts_with_routes = Post.query.filter_by(published=True).join(GPXFile).all()
+
+ return render_template('community/index.html', posts=posts, posts_with_routes=posts_with_routes)
@community.route('/post/
+ Discover epic motorcycle routes, share your adventures, and connect with fellow riders across Romania's stunning landscapes.
+
+ Click on any route to view the adventure story β’ Routes are updated live as new trips are shared
+ {{ post.author.nickname }} {{ post.created_at.strftime('%b %d, %Y') }} {{ post.subtitle }}
+ {{ post.content[:120] }}{% if post.content|length > 120 %}...{% endif %}
+
+ Be the first to share your motorcycle adventure and map your route across Romania!
+
+ Create a detailed story of your motorcycle journey through Romania
+
+ ποΈ Motorcycle Adventures Romania
+
+ πΊοΈ Interactive Route Map
+ Latest Adventures
+
+
+
+ {{ post.title }}
+
+
+
+ {% if post.subtitle %}
+ No Adventures Yet
+
+ ποΈ Share Your Adventure
+
+