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
| Column | Type | Constraints |
|---|---|---|
id | uuid | Primary key, default gen_random_uuid() |
user_id | uuid | Foreign key → auth.users(id), NOT NULL |
name | text | NOT NULL |
description | text | Nullable |
instructor | text | Nullable |
room | text | Nullable |
section | text | NOT NULL |
day_of_week | int4 | 1–7, NOT NULL |
start_time | time | NOT NULL |
end_time | time | NOT NULL |
color | text | Nullable, hex string |
created_at | timestamptz | Default now() |
updated_at | timestamptz | Default now() |
is_deleted | bool | Default 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
| Column | Type | Constraints |
|---|---|---|
id | uuid | Primary key |
user_id | uuid | Foreign key → auth.users(id) |
class_item_id | uuid | Nullable, foreign key → class_items(id) |
title | text | NOT NULL |
body | text | Nullable |
remind_at | timestamptz | NOT NULL |
is_completed | bool | Default false |
is_deleted | bool | Default false |
created_at | timestamptz | Default now() |
updated_at | timestamptz | Default 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
| Column | Type | Constraints |
|---|---|---|
id | uuid | Primary key |
user_id | uuid | Foreign key → auth.users(id) |
name | text | NOT NULL |
sort_order | int4 | Default 0 |
is_active | bool | Default false |
is_deleted | bool | Default false |
created_at | timestamptz | Default now() |
updated_at | timestamptz | Default 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
sectionfield) - 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_idand enforced by RLS
Soft Deletes
All models use an is_deleted boolean flag instead of hard deletes. This enables:
- Sync conflict resolution — Deleted items can be reconciled across devices
- Undo support — Restore recently deleted items before sync
- 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 usecamelCase TimeOfDayis serialized as"HH:mm"stringsDateTimeis serialized as ISO 8601 strings with timezone- UUIDs are stored as strings in Dart,
uuidtype in PostgreSQL