diff --git a/dashboard/habits.html b/dashboard/habits.html
new file mode 100644
index 0000000..a25884b
--- /dev/null
+++ b/dashboard/habits.html
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+ Echo · Habit Tracker
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Nicio obișnuință încă. Creează prima!
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dashboard/habits.json b/dashboard/habits.json
index e2e3ac1..0a4b66b 100644
--- a/dashboard/habits.json
+++ b/dashboard/habits.json
@@ -1,14 +1,4 @@
{
- "lastUpdated": "2026-02-10T11:40:08.703720",
- "habits": [
- {
- "id": "habit-1770723608703",
- "name": "Water Plants",
- "frequency": "daily",
- "createdAt": "2026-02-10T11:40:08.703082",
- "completions": [
- "2026-02-10"
- ]
- }
- ]
+ "lastUpdated": "2026-02-10T11:59:02.042Z",
+ "habits": []
}
\ No newline at end of file
diff --git a/dashboard/test_habits_html.py b/dashboard/test_habits_html.py
new file mode 100644
index 0000000..e56deca
--- /dev/null
+++ b/dashboard/test_habits_html.py
@@ -0,0 +1,240 @@
+#!/usr/bin/env python3
+"""
+Test suite for habits.html page structure
+
+Tests:
+1. File exists
+2. Valid HTML5 structure
+3. Uses common.css and swipe-nav.js
+4. Has navigation bar matching dashboard style
+5. Page title 'Habit Tracker' in header
+6. Empty state message 'Nicio obișnuință încă. Creează prima!'
+7. Add habit button with '+' icon (lucide)
+"""
+
+import os
+import re
+from html.parser import HTMLParser
+
+# Path to habits.html
+HABITS_HTML_PATH = 'dashboard/habits.html'
+
+class HTMLStructureParser(HTMLParser):
+ """Parser to extract specific elements from HTML"""
+ def __init__(self):
+ super().__init__()
+ self.title_text = None
+ self.css_files = []
+ self.js_files = []
+ self.nav_items = []
+ self.page_title = None
+ self.empty_state_message = None
+ self.has_add_button = False
+ self.has_lucide_plus = False
+ self.in_title = False
+ self.in_page_title = False
+ self.in_empty_message = False
+ self.in_button = False
+ self.current_class = None
+
+ def handle_starttag(self, tag, attrs):
+ attrs_dict = dict(attrs)
+
+ # Track CSS and JS files
+ if tag == 'link' and attrs_dict.get('rel') == 'stylesheet':
+ self.css_files.append(attrs_dict.get('href', ''))
+ if tag == 'script' and 'src' in attrs_dict:
+ self.js_files.append(attrs_dict.get('src'))
+
+ # Track title tag
+ if tag == 'title':
+ self.in_title = True
+
+ # Track page title (h1 with class page-title)
+ if tag == 'h1' and 'page-title' in attrs_dict.get('class', ''):
+ self.in_page_title = True
+
+ # Track nav items
+ if tag == 'a' and 'nav-item' in attrs_dict.get('class', ''):
+ href = attrs_dict.get('href', '')
+ classes = attrs_dict.get('class', '')
+ self.nav_items.append({'href': href, 'classes': classes})
+
+ # Track empty state message
+ if 'empty-state-message' in attrs_dict.get('class', ''):
+ self.in_empty_message = True
+
+ # Track add habit button
+ if tag == 'button' and 'add-habit-btn' in attrs_dict.get('class', ''):
+ self.has_add_button = True
+ self.in_button = True
+
+ # Track lucide plus icon in button context
+ if self.in_button and tag == 'i':
+ lucide_attr = attrs_dict.get('data-lucide', '')
+ if 'plus' in lucide_attr:
+ self.has_lucide_plus = True
+
+ def handle_endtag(self, tag):
+ if tag == 'title':
+ self.in_title = False
+ if tag == 'h1':
+ self.in_page_title = False
+ if tag == 'p':
+ self.in_empty_message = False
+ if tag == 'button':
+ self.in_button = False
+
+ def handle_data(self, data):
+ if self.in_title:
+ self.title_text = data.strip()
+ if self.in_page_title:
+ self.page_title = data.strip()
+ if self.in_empty_message:
+ self.empty_state_message = data.strip()
+
+def test_file_exists():
+ """Test 1: File exists"""
+ assert os.path.exists(HABITS_HTML_PATH), f"File {HABITS_HTML_PATH} not found"
+ print("✓ Test 1: File exists")
+
+def test_valid_html5():
+ """Test 2: Valid HTML5 structure"""
+ with open(HABITS_HTML_PATH, 'r', encoding='utf-8') as f:
+ content = f.read()
+
+ # Check DOCTYPE
+ assert content.strip().startswith(''), "Missing or incorrect DOCTYPE"
+
+ # Check required tags
+ required_tags = ['', '', '', '']
+ for tag in required_tags:
+ assert tag in content, f"Missing required tag: {tag}"
+
+ # Check html lang attribute
+ assert 'lang="ro"' in content or "lang='ro'" in content, "Missing lang='ro' attribute on html tag"
+
+ print("✓ Test 2: Valid HTML5 structure")
+
+def test_uses_common_css_and_swipe_nav():
+ """Test 3: Uses common.css and swipe-nav.js"""
+ with open(HABITS_HTML_PATH, 'r', encoding='utf-8') as f:
+ content = f.read()
+
+ parser = HTMLStructureParser()
+ parser.feed(content)
+
+ # Check for common.css
+ assert any('common.css' in css for css in parser.css_files), "Missing common.css"
+
+ # Check for swipe-nav.js
+ assert any('swipe-nav.js' in js for js in parser.js_files), "Missing swipe-nav.js"
+
+ print("✓ Test 3: Uses common.css and swipe-nav.js")
+
+def test_navigation_bar():
+ """Test 4: Has navigation bar matching dashboard style"""
+ with open(HABITS_HTML_PATH, 'r', encoding='utf-8') as f:
+ content = f.read()
+
+ parser = HTMLStructureParser()
+ parser.feed(content)
+
+ # Check that we have nav items
+ assert len(parser.nav_items) >= 4, f"Expected at least 4 nav items, found {len(parser.nav_items)}"
+
+ # Check for Dashboard nav item
+ dashboard_items = [item for item in parser.nav_items if 'index.html' in item['href']]
+ assert len(dashboard_items) > 0, "Missing Dashboard nav item"
+
+ # Check for habits nav item with active class
+ habits_items = [item for item in parser.nav_items if 'habits.html' in item['href']]
+ assert len(habits_items) > 0, "Missing Habits nav item"
+ assert any('active' in item['classes'] for item in habits_items), "Habits nav item should have 'active' class"
+
+ # Check for header element with class 'header'
+ assert '