Login and Dashboard added
This commit is contained in:
parent
962d611b09
commit
058b7f8233
8
.idea/do-tracker.iml
generated
Normal file
8
.idea/do-tracker.iml
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="jdk" jdkName="Python 3.13 virtualenv at ~/Projects/do-tracker/venv" jdkType="Python SDK" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
||||||
7
.idea/misc.xml
generated
Normal file
7
.idea/misc.xml
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Black">
|
||||||
|
<option name="sdkName" value="Python 3.13 virtualenv at ~/Projects/do-tracker/venv" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13 virtualenv at ~/Projects/do-tracker/venv" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
||||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/do-tracker.iml" filepath="$PROJECT_DIR$/.idea/do-tracker.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
143
.idea/workspace.xml
generated
Normal file
143
.idea/workspace.xml
generated
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="AutoImportSettings">
|
||||||
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
|
</component>
|
||||||
|
<component name="ChangeListManager">
|
||||||
|
<list default="true" id="5112d569-3a3f-4a44-9bd9-2c9295e7fe64" name="Changes" comment="Web front enabled basic flask setup">
|
||||||
|
<change afterPath="$PROJECT_DIR$/app/templates/login.html" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/app/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/__init__.py" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/app/auth.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/auth.py" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/app/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/models.py" afterDir="false" />
|
||||||
|
</list>
|
||||||
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||||
|
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||||
|
</component>
|
||||||
|
<component name="FileTemplateManagerImpl">
|
||||||
|
<option name="RECENT_TEMPLATES">
|
||||||
|
<list>
|
||||||
|
<option value="HTML File" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="Git.Settings">
|
||||||
|
<option name="RECENT_BRANCH_BY_REPOSITORY">
|
||||||
|
<map>
|
||||||
|
<entry key="$PROJECT_DIR$" value="main" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||||
|
</component>
|
||||||
|
<component name="HighlightingSettingsPerFile">
|
||||||
|
<setting file="file://$PROJECT_DIR$/run.py" root0="FORCE_HIGHLIGHTING" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectColorInfo"><![CDATA[{
|
||||||
|
"associatedIndex": 2
|
||||||
|
}]]></component>
|
||||||
|
<component name="ProjectId" id="2xzZKYTQ3ONQyWMQvvsDEzRY2pu" />
|
||||||
|
<component name="ProjectLevelVcsManager">
|
||||||
|
<ConfirmationsSetting value="2" id="Add" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectViewState">
|
||||||
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
|
<option name="showLibraryContents" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PropertiesComponent"><![CDATA[{
|
||||||
|
"keyToString": {
|
||||||
|
"DefaultHtmlFileTemplate": "HTML File",
|
||||||
|
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
||||||
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
|
"RunOnceActivity.git.unshallow": "true",
|
||||||
|
"git-widget-placeholder": "main",
|
||||||
|
"settings.editor.selected.configurable": "preferences.lookFeel"
|
||||||
|
}
|
||||||
|
}]]></component>
|
||||||
|
<component name="TaskManager">
|
||||||
|
<task active="true" id="Default" summary="Default task">
|
||||||
|
<changelist id="5112d569-3a3f-4a44-9bd9-2c9295e7fe64" name="Changes" comment="" />
|
||||||
|
<created>1748942798494</created>
|
||||||
|
<option name="number" value="Default" />
|
||||||
|
<option name="presentableId" value="Default" />
|
||||||
|
<updated>1748942798494</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00001" summary="First Commit">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1748943061863</created>
|
||||||
|
<option name="number" value="00001" />
|
||||||
|
<option name="presentableId" value="LOCAL-00001" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1748943061863</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00002" summary="First Commit">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1748943110291</created>
|
||||||
|
<option name="number" value="00002" />
|
||||||
|
<option name="presentableId" value="LOCAL-00002" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1748943110291</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00003" summary="First Commit">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1748943342764</created>
|
||||||
|
<option name="number" value="00003" />
|
||||||
|
<option name="presentableId" value="LOCAL-00003" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1748943342764</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00004" summary="Web front enabled basic flask setup">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1748943934876</created>
|
||||||
|
<option name="number" value="00004" />
|
||||||
|
<option name="presentableId" value="LOCAL-00004" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1748943934876</updated>
|
||||||
|
</task>
|
||||||
|
<option name="localTasksCounter" value="5" />
|
||||||
|
<servers />
|
||||||
|
</component>
|
||||||
|
<component name="Vcs.Log.Tabs.Properties">
|
||||||
|
<option name="RECENT_FILTERS">
|
||||||
|
<map>
|
||||||
|
<entry key="Branch">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<RecentGroup>
|
||||||
|
<option name="FILTER_VALUES">
|
||||||
|
<option value="origin/main" />
|
||||||
|
</option>
|
||||||
|
</RecentGroup>
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
<option name="TAB_STATES">
|
||||||
|
<map>
|
||||||
|
<entry key="MAIN">
|
||||||
|
<value>
|
||||||
|
<State>
|
||||||
|
<option name="FILTERS">
|
||||||
|
<map>
|
||||||
|
<entry key="branch">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="main" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</State>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="VcsManagerConfiguration">
|
||||||
|
<MESSAGE value="First Commit" />
|
||||||
|
<MESSAGE value="Web front enabled basic flask setup" />
|
||||||
|
<option name="LAST_COMMIT_MESSAGE" value="Web front enabled basic flask setup" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@ -1,20 +1,25 @@
|
|||||||
from flask import Flask
|
from flask import Flask
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
from flask_login import LoginManager
|
##from flask_login import LoginManager
|
||||||
|
|
||||||
db = SQLAlchemy()
|
db = SQLAlchemy()
|
||||||
login_manager = LoginManager()
|
#login_manager = LoginManager()
|
||||||
|
|
||||||
def create_app():
|
def create_app():
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.config['SECRET_KEY'] = 'devkey' # Change this for production
|
app.config['SECRET_KEY'] = 'devkey' # Change this later
|
||||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///do_tracker.db'
|
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///do_tracker.db'
|
||||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||||
|
|
||||||
db.init_app(app)
|
db.init_app(app)
|
||||||
login_manager.init_app(app)
|
# login_manager.init_app(app)
|
||||||
|
|
||||||
from .routes import main as main_blueprint
|
from .routes import main as main_blueprint
|
||||||
app.register_blueprint(main_blueprint)
|
app.register_blueprint(main_blueprint)
|
||||||
|
|
||||||
|
from .auth import auth as auth_blueprint
|
||||||
|
app.register_blueprint(auth_blueprint)
|
||||||
|
|
||||||
|
from . import models # <-- 🔥 this is what was missing
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|||||||
26
app/auth.py
26
app/auth.py
@ -0,0 +1,26 @@
|
|||||||
|
from flask import Blueprint, render_template, redirect, request, session, url_for, flash
|
||||||
|
from .models import Store
|
||||||
|
from . import db
|
||||||
|
|
||||||
|
auth = Blueprint('auth', __name__)
|
||||||
|
|
||||||
|
@auth.route('/login', methods=['GET', 'POST'])
|
||||||
|
def login():
|
||||||
|
if request.method == 'POST':
|
||||||
|
store_id = request.form.get('store_id')
|
||||||
|
password = request.form.get('password')
|
||||||
|
store = Store.query.filter_by(id=store_id, password=password).first()
|
||||||
|
if store:
|
||||||
|
session['store_id'] = store.id
|
||||||
|
session['store_name'] = store.name
|
||||||
|
flash(f"Logged in as {store.name}", "success")
|
||||||
|
return redirect(url_for('main.store_dashboard'))
|
||||||
|
else:
|
||||||
|
flash("Invalid store ID or password", "danger")
|
||||||
|
return render_template('login.html')
|
||||||
|
|
||||||
|
@auth.route('/logout')
|
||||||
|
def logout():
|
||||||
|
session.clear()
|
||||||
|
flash("Logged out successfully", "info")
|
||||||
|
return redirect(url_for('auth.login'))
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
from . import db
|
||||||
|
|
||||||
|
class Store(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True) # Store number like 210
|
||||||
|
name = db.Column(db.String(100), nullable=False)
|
||||||
|
password = db.Column(db.String(128), nullable=False) # plaintext for now (hash later)
|
||||||
|
|
||||||
|
class DeliveryOrder(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
do_number = db.Column(db.String(50), unique=True, nullable=False)
|
||||||
|
delivery_number = db.Column(db.String(50), nullable=False)
|
||||||
|
final_location = db.Column(db.Integer, db.ForeignKey('store.id'), nullable=False)
|
||||||
|
created_by = db.Column(db.String(100), nullable=False)
|
||||||
|
status = db.Column(db.String(50), default='Ready for Collection')
|
||||||
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||||
|
collected_by = db.Column(db.String(100), nullable=True)
|
||||||
|
|
||||||
|
movements = db.relationship('Movement', backref='delivery_order', cascade='all, delete-orphan')
|
||||||
|
|
||||||
|
class Movement(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
do_id = db.Column(db.Integer, db.ForeignKey('delivery_order.id'), nullable=False)
|
||||||
|
branch_id = db.Column(db.Integer, db.ForeignKey('store.id'), nullable=False)
|
||||||
|
arrived_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||||
|
departed_at = db.Column(db.DateTime, nullable=True)
|
||||||
|
handled_by = db.Column(db.String(100), nullable=False)
|
||||||
|
comment = db.Column(db.Text, nullable=True)
|
||||||
@ -1,7 +1,31 @@
|
|||||||
from flask import Blueprint
|
from flask import Blueprint, render_template, redirect, url_for, session, flash
|
||||||
|
from .models import DeliveryOrder
|
||||||
|
|
||||||
main = Blueprint('main', __name__)
|
main = Blueprint('main', __name__)
|
||||||
|
|
||||||
@main.route("/")
|
|
||||||
|
@main.route('/')
|
||||||
def home():
|
def home():
|
||||||
return "<h1>DO Tracker Online</h1><p>Welcome to the system.</p>"
|
return """
|
||||||
|
<h1>DO Tracker Online</h1>
|
||||||
|
<p><a href='/login'>Login as Store</a></p>
|
||||||
|
<p><a href='/store'>Store Dashboard</a></p>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@main.route('/store')
|
||||||
|
def store_dashboard():
|
||||||
|
if 'store_id' not in session:
|
||||||
|
flash("You must be logged in to access the store dashboard.", "warning")
|
||||||
|
return redirect(url_for('auth.login'))
|
||||||
|
|
||||||
|
store_name = session.get('store_name')
|
||||||
|
|
||||||
|
return f"""
|
||||||
|
<h1>Welcome, {store_name}</h1>
|
||||||
|
<p><a href='/logout'>Logout</a></p>
|
||||||
|
<ul>
|
||||||
|
<li><a href='/store/do-entry'>Enter New DO</a> (coming next)</li>
|
||||||
|
<li><a href='/store/track'>Track DOs</a> (coming soon)</li>
|
||||||
|
</ul>
|
||||||
|
"""
|
||||||
|
|||||||
21
app/templates/login.html
Normal file
21
app/templates/login.html
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Store Login</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Store Login</h1>
|
||||||
|
<form method="POST">
|
||||||
|
<label>Store ID:</label><br>
|
||||||
|
<input type="text" name="store_id"><br>
|
||||||
|
<label>Password:</label><br>
|
||||||
|
<input type="password" name="password"><br><br>
|
||||||
|
<button type="submit">Login</button>
|
||||||
|
</form>
|
||||||
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||||
|
{% for category, message in messages %}
|
||||||
|
<p style="color:red;">{{ message }}</p>
|
||||||
|
{% endfor %}
|
||||||
|
{% endwith %}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
x
Reference in New Issue
Block a user