MySched

Data Models

MySched uses three core models that map directly to Supabase tables. All models include serialization methods for JSON/database interop and are immutable by convention.

ClassItem

The primary model representing a single class entry in a student's schedule.

Dart
class ClassItem {
  final String id;
  final String userId;
  final String name;           // e.g., "CS 101"
  final String? description;   // e.g., "Intro to Computer Science"
  final String? instructor;
  final String? room;
  final String section;        // Section identifier
  final int dayOfWeek;         // 1 = Monday, 7 = Sunday
  final TimeOfDay startTime;
  final TimeOfDay endTime;
  final String? color;         // Hex color for UI display
  final DateTime createdAt;
  final DateTime updatedAt;
  final bool isDeleted;        // Soft delete flag

  // Serialization
  Map<String, dynamic> toJson() => { ... };
  factory ClassItem.fromJson(Map<String, dynamic> json) => ...;
}

Database table: class_items

ColumnTypeConstraints
iduuidPrimary key, default gen_random_uuid()
user_iduuidForeign key → auth.users(id), NOT NULL
nametextNOT NULL
descriptiontextNullable
instructortextNullable
roomtextNullable
sectiontextNOT NULL
day_of_weekint41–7, NOT NULL
start_timetimeNOT NULL
end_timetimeNOT NULL
colortextNullable, hex string
created_attimestamptzDefault now()
updated_attimestamptzDefault now()
is_deletedboolDefault false

ReminderEntry

Represents a reminder attached to a class or standalone.

Dart
class ReminderEntry {
  final String id;
  final String userId;
  final String? classItemId;   // Nullable — standalone reminders
  final String title;
  final String? body;
  final DateTime remindAt;
  final bool isCompleted;
  final bool isDeleted;
  final DateTime createdAt;
  final DateTime updatedAt;

  Map<String, dynamic> toJson() => { ... };
  factory ReminderEntry.fromJson(Map<String, dynamic> json) => ...;
}

Database table: reminders

ColumnTypeConstraints
iduuidPrimary key
user_iduuidForeign key → auth.users(id)
class_item_iduuidNullable, foreign key → class_items(id)
titletextNOT NULL
bodytextNullable
remind_attimestamptzNOT NULL
is_completedboolDefault false
is_deletedboolDefault false
created_attimestamptzDefault now()
updated_attimestamptzDefault now()

Section

Groups class items into a named schedule (e.g., "Fall 2024", "Spring 2025").

Dart
class Section {
  final String id;
  final String userId;
  final String name;           // e.g., "Fall 2024"
  final int sortOrder;         // Display ordering
  final bool isActive;         // Currently selected section
  final bool isDeleted;
  final DateTime createdAt;
  final DateTime updatedAt;

  Map<String, dynamic> toJson() => { ... };
  factory Section.fromJson(Map<String, dynamic> json) => ...;
}

Database table: sections

ColumnTypeConstraints
iduuidPrimary key
user_iduuidForeign key → auth.users(id)
nametextNOT NULL
sort_orderint4Default 0
is_activeboolDefault false
is_deletedboolDefault false
created_attimestamptzDefault now()
updated_attimestamptzDefault now()

Model Relationships

Section (1) ──── (*) ClassItem (1) ──── (*) ReminderEntry
   │                    │                       │
   └── user_id          └── user_id             └── user_id
       section               class_item_id
  • A Section contains many ClassItems (linked by section field)
  • A ClassItem can have many ReminderEntries (linked by class_item_id)
  • ReminderEntries can also be standalone (null class_item_id)
  • All models are scoped to a user via user_id and enforced by RLS

Soft Deletes

All models use an is_deleted boolean flag instead of hard deletes. This enables:

  1. Sync conflict resolution — Deleted items can be reconciled across devices
  2. Undo support — Restore recently deleted items before sync
  3. Audit trail — Maintain history of user actions

Queries filter on is_deleted = false by default. The sync engine handles permanent cleanup after a configurable retention period.

Serialization Conventions

  • All models use toJson() / fromJson() factory constructors
  • Database column names use snake_case; Dart fields use camelCase
  • TimeOfDay is serialized as "HH:mm" strings
  • DateTime is serialized as ISO 8601 strings with timezone
  • UUIDs are stored as strings in Dart, uuid type in PostgreSQL