diff --git a/app.py b/app.py index 29f2517..50b1abd 100644 --- a/app.py +++ b/app.py @@ -22,19 +22,8 @@ def get_user_id(): def is_logged_in(): return 'user_id' in session -# --- Routes --- - -@app.route('/') -def index(): - # If not logged in, show the landing page instead of redirecting - if not is_logged_in(): - return render_template('landing.html') - - user_id = get_user_id() - - # Get all activities - activities = list(db.activities.find({'user_id': user_id})) - +# --- Logic Helpers --- +def get_dashboard_context(user_id): # Check for active time entry current_entry = db.time_entries.find_one({ 'user_id': user_id, @@ -49,15 +38,14 @@ def index(): current_entry['activity_name'] = active_activity['name'] current_entry['activity_color'] = active_activity.get('color', '#3498db') - # Logic for fetching tasks: - # 1. Fetch Session Specific Tasks (linked via time_entry_id) + # 1. Session Tasks session_tasks = list(db.tasks.find({ 'user_id': user_id, 'status': 'open', 'time_entry_id': current_entry['_id'] })) - # 2. Fetch Contextual Tasks (linked via activity_id, no time_entry_id) + # 2. Context Tasks context_criteria = { 'user_id': user_id, 'status': 'open', @@ -67,27 +55,56 @@ def index(): } current_subcat = current_entry.get('subcategory') - if current_subcat: - # If active entry has subcategory: Show tasks matching that subcategory OR general tasks (no subcategory) - context_criteria['$or'] = [ - {'subcategory': current_subcat}, - {'subcategory': {'$in': [None, '']}} - ] + context_criteria['$or'] = [{'subcategory': current_subcat}, {'subcategory': {'$in': [None, '']}}] else: - # If active entry has NO subcategory: Show only General tasks (no subcategory assigned) - # This hides specific subcategory tasks when just tracking the general activity context_criteria['subcategory'] = {'$in': [None, '']} context_tasks = list(db.tasks.find(context_criteria)) - active_tasks = session_tasks + context_tasks + + return current_entry, active_tasks + +# --- Routes --- + +@app.route('/') +def index(): + # If not logged in, show the landing page instead of redirecting + if not is_logged_in(): + return render_template('landing.html') + + user_id = get_user_id() + + # Get all activities + activities = list(db.activities.find({'user_id': user_id})) + + # Use shared logic + current_entry, active_tasks = get_dashboard_context(user_id) return render_template('dashboard.html', activities=activities, current_entry=current_entry, tasks=active_tasks) +@app.route('/api/sync_check') +def sync_check(): + if not is_logged_in(): return jsonify({'error': 'auth'}), 401 + user_id = get_user_id() + + current_entry, active_tasks = get_dashboard_context(user_id) + + entry_id = str(current_entry['_id']) if current_entry else 'none' + + # Create simple hash of tasks (IDs joined string) + # If a task is completed, it drops from this list -> hash changes -> client reloads + task_ids = sorted([str(t['_id']) for t in active_tasks]) + tasks_hash = ','.join(task_ids) + + return jsonify({ + 'entry_hash': entry_id, + 'tasks_hash': tasks_hash + }) + @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'POST': @@ -228,6 +245,7 @@ def start_timer_bg(activity_id): return jsonify({ 'status': 'success', + 'entry_id': str(new_entry_id), 'start_time': start_time.isoformat(), 'activity_name': activity['name'], 'activity_color': activity.get('color', '#3498db') diff --git a/templates/dashboard.html b/templates/dashboard.html index 9aaaaf1..c3de700 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -20,10 +20,12 @@ max-width: none !important; } - /* Fix container widths */ + /* Fix container widths to be full width */ .main-content { text-align: center; - min-width: 0 !important; /* Override inline style */ + width: 100% !important; /* Force full width */ + flex: none !important; /* Disable flex scaling from desktop */ + min-width: 0 !important; } .main-content h2 { margin-left: auto; @@ -33,6 +35,7 @@ /* Layout Reordering: Sidebar (Active Timer) first */ .dashboard-container { flex-direction: column; + align-items: stretch !important; /* Force children to stretch full width */ } .sidebar-container { order: -1; /* Visualize first */ @@ -259,6 +262,12 @@ .then(res => res.json()) .then(data => { if(data.status === 'success') { + // UPDATE LOCAL HASH TO PREVENT SYNC RELOAD + if (data.entry_id) { + localEntryHash = data.entry_id; + console.log("Local state updated intentionally. Reload prevented."); + } + // 2. Start Local Timer UI startTime = new Date(data.start_time).getTime(); clearInterval(timerInterval); @@ -365,4 +374,54 @@ + + + {% endblock %}