Skip to content

Repeated Task Specification

mt-xing edited this page Apr 21, 2019 · 2 revisions

Features

Task Creation

When creating a task, the user should be able to specify whether it's a one time task or a repeated task. For all kinds of tasks, the user should be able to specify a due date with precision to minutes. All legacy tasks should be migrated so that the due date's time component becomes 11:59 PM.

UNDO creation should work just fine.

Task Edit

When finish editing a repeated task, the user should be prompted to specify whether they want to fork or update the master template.

PROBLEM: what about task reordering?

Task Deletion

When deleting a repeated task, the user should be prompted to specify whether they want to delete one or all of the repetitions.

UNDO deletion should work just fine.

Database Structure

type FirestoreCommon = {
  readonly owner: string;
  readonly order: number;
  readonly lastUpdated: firestore.Timestamp;
};

type FirestoreTaskCommon = FirestoreCommon & {
  readonly name: string;
  readonly tag: string;
  readonly date: firestore.Timestamp;
  readonly complete: boolean;
  readonly inFocus: boolean;
  readonly children: string[]; // pointers to sub-tasks
};

type RepeatingPattern =
  | { readonly type: 'WEEKLY'; readonly bitSet: number /* 7-bit */ }
  | { readonly type: 'BIWEEKLY'; readonly bitSet: number /* 14-bit */ }
  | { readonly type: 'MONTHLY'; readonly bitSet: number /* 31-bit */ };
    // Consider scrapping monthly for MVP

type ForkedTaskMetaData = {
  readonly forkId: string | null; // null means one of the repetition is deleted
  readonly replaceDate: firestore.Timestamp;
};

type FirestoreMasterTask = FirestoreTaskCommon & {
  readonly type: 'MASTER_TEMPLATE';
  // in master task, we only use the time component of the date
  readonly repeats: {
    readonly startDate: firestore.Timestamp | null;
    readonly endDate: firestore.Timestamp | null;
    readonly pattern: RepeatingPattern;
  };
  // fork id can only points to a one time task
  readonly forks: ForkedTaskMetaData[];
};

type FirestoreOneTimeTask = FirestoreTaskCommon & { readonly type: 'ONE_TIME' }

type FirestoreLegacyTask = FirestoreTaskCommon & {};

// all these tasks stay in 'samwise-tasks'
// FirestoreLegacyTask should eventually be converted to FirestoreOneTimeTask.
type FirestoreTask = FirestoreMasterTask | FirestoreOneTimeTask | FirestoreLegacyTask;