from flask_login import UserMixin from datetime import datetime from werkzeug.security import generate_password_hash, check_password_hash # Sleep quality and status choices for validation SLEEP_QUALITY_CHOICES = ['poor', 'fair', 'good', 'excellent'] STATUS_CHOICES = ['todo', 'doing', 'done', 'cancelled'] ITEM_TYPE_CHOICES = ['bullet', 'gratitude', 'sleep', 'note', 'task'] def init_db_models(db): """Initialize all model classes with the SQLAlchemy instance. Call this once in create_app() after db is created. """ class User(UserMixin, db.Model): __tablename__ = 'user' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64), unique=True, nullable=False) password_hash = db.Column(db.String(128), nullable=False) logs = db.relationship('DailyLog', backref='user', lazy=True, cascade='all, delete-orphan') def set_password(self, password): self.password_hash = generate_password_hash(password) def check_password(self, password): return check_password_hash(self.password_hash, password) class UserSettings(db.Model): __tablename__ = 'user_settings' id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False, unique=True) theme = db.Column(db.String(10), default='light') font_size = db.Column(db.Integer, default=18) created_at = db.Column(db.DateTime, default=datetime.utcnow) updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) class DailyLog(db.Model): __tablename__ = 'daily_log' id = db.Column(db.Integer, primary_key=True) date = db.Column(db.Date, unique=True, nullable=False) prompt = db.Column(db.Text, nullable=True) notes = db.Column(db.Text, nullable=True) gratitude = db.Column(db.JSON, default=list) bedtime = db.Column(db.String(20), nullable=True) wake_time = db.Column(db.String(20), nullable=True) sleep_quality = db.Column(db.String(10), nullable=True) # Enum stored as string mood = db.Column(db.String(50), nullable=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow) updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) items = db.relationship('DailyLogItem', backref='log', lazy=True, cascade='all, delete-orphan') @property def gratitude_list(self): if not self.gratitude: return ['', '', ''] return self.gratitude + [''] * (3 - len(self.gratitude)) @gratitude_list.setter def gratitude_list(self, value): self.gratitude = value[:3] if value else [] def __repr__(self): return f'' class DailyLogItem(db.Model): __tablename__ = 'daily_log_item' id = db.Column(db.Integer, primary_key=True) log_id = db.Column(db.Integer, db.ForeignKey('daily_log.id'), nullable=False) type = db.Column(db.String(20), nullable=False) # Enum stored as string symbol = db.Column(db.String(10), default='•') text = db.Column(db.Text, nullable=True) created_at = db.Column(db.DateTime, default=datetime.utcnow) status = db.Column(db.String(10), default='todo') # Enum stored as string __table_args__ = ( db.Index('ix_log_id', 'log_id'), db.Index('ix_log_id_status', 'log_id', 'status'), db.Index('ix_type', 'type'), ) def __repr__(self): return f'' # Store references on module for import by other blueprints init_db_models.User = User init_db_models.UserSettings = UserSettings init_db_models.DailyLog = DailyLog init_db_models.DailyLogItem = DailyLogItem