maa3520 1 vuosi sitten
vanhempi
commit
d74533c46d
3 muutettua tiedostoa jossa 245 lisäystä ja 101 poistoa
  1. 15 7
      src/Reminder.ts
  2. 77 0
      src/ReminderApp.ts
  3. 153 94
      src/RemindersHandler.ts

+ 15 - 7
src/Reminder.ts

@@ -17,13 +17,21 @@ export default class Reminder {
    * @param description - The full description of reminder
    * @param tag - The keyword used to help categorize reminder
    */
-  constructor() {}
+   private _description: string;
+   private _tag: string;
+   private _isCompleted: boolean;
+ 
+   constructor(description: string, tag: string) {
+     this._description = description;
+     this._tag = tag;
+     this._isCompleted = false;
+   }
 
   /**
    * Returns the description of this reminder.
    */
   public get description(): string {
-    throw new Error('Not yet implemented');
+    return this._description;
   }
 
   /**
@@ -31,14 +39,14 @@ export default class Reminder {
    * @param description - The full description of reminder.
    */
   public set description(description: string) {
-    throw new Error('Not yet implemented');
+    this._description = description;
   }
 
   /**
    * Returns the tag associated with this reminder.
    */
   public get tag(): string {
-    throw new Error('Not yet implemented');
+    return this._tag;
   }
 
   /**
@@ -46,20 +54,20 @@ export default class Reminder {
    * @param tag - The keyword used to help categorize this reminder
    */
   public set tag(tag: string) {
-    throw new Error('Not yet implemented');
+    this._tag = tag;
   }
 
   /**
    * Returns true if reminder is completed, false otherwise.
    */
   public get isCompleted(): boolean {
-    throw new Error('Not yet implemented');
+    return this._isCompleted;
   }
 
   /**
    * Toggles reminder completion status true ⬅ ➡ false.
    */
   public toggleCompletion(): void {
-    throw new Error('Not yet implemented');
+    this._isCompleted = !this._isCompleted;
   }
 }

+ 77 - 0
src/ReminderApp.ts

@@ -66,6 +66,26 @@ export default class ReminderApp {
             ( 3 ) Take result from ( 2 ) and toggle that reminder's completion (this._remindersHandler.toggleCompletion)
             ( 4 ) Logger.log('\n  🏁   Reminder Completion Toggled');
         */
+    // 檢查是否有提醒
+    if (this._remindersHandler.size() === 0) {
+      Logger.log("\n  ⚠️  You have no reminders");
+      return;
+    }
+
+    // (1) 顯示所有提醒
+    Logger.logReminders(this._remindersHandler.reminders);
+
+    // (2) 詢問用戶選擇要切換完成狀態的提醒編號
+    const reminderIndex = this.getUserChoice("Choose a reminder number to toggle", true);
+
+    // 將用戶選擇從字符串轉換為基於零的索引
+    const index = parseInt(reminderIndex) - 1;
+
+    // (3) 切換所選提醒的完成狀態
+    this._remindersHandler.toggleCompletion(index);
+
+    // (4) 記錄提醒完成狀態已切換
+    Logger.log("\n  🏁   Reminder Completion Toggled");
   }
 
   /**
@@ -83,6 +103,31 @@ export default class ReminderApp {
             ( 5 ) If user wishes to also toggle reminder status, do so (this._remindersHandler.toggleCompletion)...feeding in ( 2 )
             ( 6 ) Logger.log('\n  🏁   Reminder Modified');
         */
+    // 檢查是否有提醒
+    if (this._remindersHandler.size() === 0) {
+      Logger.log("\n  ⚠️  You have no reminders");
+      return;
+    }
+
+    // (1) 顯示所有提醒
+    Logger.logReminders(this._remindersHandler.reminders);
+
+    // (2) 讓用戶選擇要編輯的提醒編號
+    const reminderIndex = this.getUserChoice("reminder number to edit", true);
+
+    // (3) 獲取用戶為提醒輸入的新描述
+    const newDescription = this.getUserChoice("new reminder description", false);
+
+    // (4) 修改提醒
+    this._remindersHandler.modifyReminder(parseInt(reminderIndex) - 1, newDescription);
+
+    // (5) 如果用戶希望切換提醒狀態
+    if (ReminderApp.checkUserToggleChoice()) {
+      this._remindersHandler.toggleCompletion(parseInt(reminderIndex) - 1);
+    }
+
+    // (6) 記錄提醒已被修改
+    Logger.log("\n  🏁   Reminder Modified");
   }
 
   /**
@@ -96,6 +141,17 @@ export default class ReminderApp {
             ( 3 ) Take result from ( 1 ) and ( 2 ) and add reminder (this._remindersHandler.addReminder)
             ( 4 ) Logger.log('\n  🏁  Reminder Added');
         */
+    // Step 1: Ask user to enter a reminder description
+    const reminderDescription = this.getUserChoice("reminder (description)", false);
+
+    // Step 2: Ask user to enter a tag for the reminder
+    const reminderTag = this.getUserChoice("tag for the reminder", false);
+
+    // Step 3: Add the reminder with the provided description and tag
+    this._remindersHandler.addReminder(reminderDescription, reminderTag);
+
+    // Step 4: Log the confirmation message
+    Logger.log("\n  🏁  Reminder Added");
   }
 
   /**
@@ -115,6 +171,18 @@ export default class ReminderApp {
               - If not, then call this.searchDescriptions(keyword) and look through each
                 individual reminder. 
     */
+    // 檢查是否有提醒
+    if (this._remindersHandler.size() === 0) {
+      Logger.log("\n  ⚠️  You have no reminders");
+      return;
+    }
+
+    // (1) 詢問用戶輸入搜索關鍵字
+    const keyword = this.getUserChoice("Enter a search keyword", false);
+
+    // (2) 執行搜索並記錄結果
+    const searchResults = this._remindersHandler.search(keyword);
+    Logger.logSearchResults(searchResults);
   }
 
   /**
@@ -127,6 +195,15 @@ export default class ReminderApp {
         otherwise
         ( 1 ) Logger.logGroupedReminders(this._remindersHandler.groupByTag());
     */
+    // 檢查是否有提醒
+    if (this._remindersHandler.size() === 0) {
+      Logger.log("\n  ⚠️  You have no reminders");
+    } else {
+      // 獲取按標籤分組的提醒
+      const groupedReminders = this._remindersHandler.groupByTag();
+      // 記錄分組的提醒
+      Logger.logGroupedReminders(groupedReminders);
+    }
   }
 
   /**

+ 153 - 94
src/RemindersHandler.ts

@@ -1,10 +1,10 @@
-import Reminder from './Reminder';
+import Reminder from "./Reminder";
 
 /**
  * A grouping of reminders based on tag (case-insensitive)
  */
 export interface RemindersGroupingByTag {
-    [tag: string]: Reminder[];
+  [tag: string]: Reminder[];
 }
 
 /**
@@ -12,95 +12,137 @@ export interface RemindersGroupingByTag {
  * @description Represents a handler that manages a list of reminders
  */
 export default class RemindersHandler {
-    private _reminders: Reminder[];
-
-    /**
-     * Creates a new RemindersHandler instance with no reminders.
-     */
-    constructor() {
-        this._reminders = [];
+  private _reminders: Reminder[];
+
+  /**
+   * Creates a new RemindersHandler instance with no reminders.
+   */
+  constructor() {
+    this._reminders = [];
+  }
+
+  /**
+   * Returns the list of reminders added so far.
+   */
+  public get reminders(): Reminder[] {
+    // 返回 _reminders 數組的副本
+    return [...this._reminders];
+  }
+
+  /**
+   * Creates a new reminder and adds it to list of reminders.
+   * @param description - The full description of reminder
+   * @param tag - The keyword used to help categorize reminder
+   */
+  public addReminder(description: string, tag: string): void {
+    const newReminder = new Reminder(description, tag);
+
+    // 將新的提醒添加到陣列中
+    this._reminders.push(newReminder);
+  }
+
+  /**
+   * Returns the reminder at specified index.
+   * @throws ReminderError if specified index is not valid
+   * @param index - The index of the reminder
+   */
+  public getReminder(index: number): Reminder {
+    if (!this.isIndexValid(index)) {
+      throw new Error("ReminderError: Invalid index");
     }
 
-    /**
-     * Returns the list of reminders added so far.
-     */
-    public get reminders(): Reminder[] {
-        throw new Error("Not yet implemented");
+    return this._reminders[index];
+  }
+
+  /**
+   * Returns true if specified index is valid, false otherwise.
+   * @param index - The position of the reminder in list of reminders
+   */
+  public isIndexValid(index: number): boolean {
+    if (this.size() === 0) return false;
+    if (index < 0 || index + 1 > this.size()) return false;
+    return true;
+  }
+
+  /**
+   * Returns the number of reminders added so far.
+   */
+  public size(): number {
+    return this._reminders.length;
+  }
+
+  /**
+   * Modifies the description of the reminder at a specified index.
+   * Silently ignores call if index is not valid.
+   * @param index - The index of the reminder
+   * @param description - The full description of reminder
+   * @param tag - The keyword used to help categorize reminder
+   */
+  public modifyReminder(index: number, description: string): void {
+    // 檢查索引是否有效
+    if (!this.isIndexValid(index)) {
+      return; // 如果索引無效,直接返回
     }
 
-    /**
-     * Creates a new reminder and adds it to list of reminders.
-     * @param description - The full description of reminder
-     * @param tag - The keyword used to help categorize reminder
-     */
-    public addReminder(description: string, tag: string): void {
-        throw new Error("Not yet implemented");
+    // 獲取特定索引處的提醒
+    const reminder = this._reminders[index];
+
+    // 更新提醒的描述
+    reminder.description = description;
+
+    // 注意:不需要顯式地將更新後的提醒存回數組,
+    // 因為 JavaScript 中對象是通過引用傳遞的
+  }
+
+  /**
+   * Toggle the completion status of the reminder at specified index.
+   * Silently ignores call if index is not valid.
+   * @param index - The index of the reminder
+   */
+  public toggleCompletion(index: number): void {
+    // 檢查索引是否有效
+    if (!this.isIndexValid(index)) {
+      return; // 如果索引無效,直接返回
     }
 
-    /**
-     * Returns the reminder at specified index.
-     * @throws ReminderError if specified index is not valid
-     * @param index - The index of the reminder
-     */
-    public getReminder(index: number): Reminder {
-        throw new Error("Not yet implemented");
-    }
+    // 獲取特定索引處的提醒
+    const reminder = this._reminders[index];
 
-    /**
-     * Returns true if specified index is valid, false otherwise.
-     * @param index - The position of the reminder in list of reminders
-     */
-        public isIndexValid(index: number): boolean {
-        if (this.size() === 0) return false;
-        if (index < 0 || index + 1 > this.size()) return false;
-        return true;
-    }
+    // 切換提醒的完成狀態
+    reminder.toggleCompletion();
 
-    /**
-     * Returns the number of reminders added so far.
-     */
-    public size(): number {
-        return this._reminders.length;
-    }
+    // 同樣地,由於 JavaScript 中對象是通過引用傳遞的,
+    // 更改將會直接反映在 `_reminders` 數組中的對應對象上
+  }
 
-    /**
-     * Modifies the description of the reminder at a specified index.
-     * Silently ignores call if index is not valid.
-     * @param index - The index of the reminder
-     * @param description - The full description of reminder
-     * @param tag - The keyword used to help categorize reminder
-     */
-    public modifyReminder(index: number, description: string): void {
-        throw new Error("Not yet implemented");
-    }
+  /**
+   * Returns a list of reminders that match the keyword
+   * All reminders with tags that match the search keyword exactly will be returned first.
+   * If none exist, then all reminders with descriptions that match the search keyword (even partially)
+   * are returned.
+   * @param keyword - Text to search for in description and tag
+   */
+  public search(keyword: string): Reminder[] {
+    const keywordLower = keyword.toLowerCase();
 
-    /**
-     * Toggle the completion status of the reminder at specified index.
-     * Silently ignores call if index is not valid.
-     * @param index - The index of the reminder
-     */
-    public toggleCompletion(index: number): void {
-        throw new Error("Not yet implemented");
-    }
+    // 首先根據標籤搜索
+    let results = this.searchTags(keywordLower);
 
-    /**
-     * Returns a list of reminders that match the keyword
-     * All reminders with tags that match the search keyword exactly will be returned first.
-     * If none exist, then all reminders with descriptions that match the search keyword (even partially)
-     * are returned.
-     * @param keyword - Text to search for in description and tag
-     */
-    public search(keyword: string): Reminder[] {
-        throw new Error("Not yet implemented");
-    }
+    // 如果沒有找到匹配的標籤,則根據描述搜索
+    if (results.length === 0) {
+        results = this.searchDescriptions(keywordLower);
+      }
+
+    return results;
+  }
 
-    /**
-     * Returns a grouping of the reminders based on tag (case-insensitive).
-     */
-    public groupByTag(): RemindersGroupingByTag {
-        const groupings: RemindersGroupingByTag = {};
+  /**
+   * Returns a grouping of the reminders based on tag (case-insensitive).
+   */
+  public groupByTag(): RemindersGroupingByTag {
+    const groupings: RemindersGroupingByTag = {};
 
-        /* Pseudocode:
+    /* Pseudocode:
         You must group the reminders by tags. 
         So you need to take this._reminders which is currently like so:
 
@@ -115,23 +157,40 @@ export default class RemindersHandler {
         }
 
         */
-       
-        return groupings;
-    }
 
-    /**
-     * Returns a list of reminders with tags that match the keyword exactly.
-     * @param keyword - Text to search for in description and tag
-     */
-    private searchTags(keyword: string): Reminder[] {
-        throw new Error("Not yet implemented");
-    }
+    // 遍歷所有提醒
+    for (const reminder of this._reminders) {
+      // 獲取標籤,並將其轉換為小寫以實現不區分大小寫
+      const tag = reminder.tag.toLowerCase();
+
+      // 如果該標籤還未在分組中則初始化
+      if (!groupings[tag]) {
+        groupings[tag] = [];
+      }
 
-    /**
-     * Returns a list of reminders with descriptions that match the keyword.
-     * @param keyword - Text to search for in description and tag
-     */
-    private searchDescriptions(keyword: string): Reminder[] {
-        throw new Error("Not yet implemented");
+      // 將提醒添加到相應標籤的分組中
+      groupings[tag].push(reminder);
     }
+
+    return groupings;
+  }
+
+  /**
+   * Returns a list of reminders with tags that match the keyword exactly.
+   * @param keyword - Text to search for in description and tag
+   */
+  private searchTags(keyword: string): Reminder[] {
+
+    // 篩選出標籤匹配的提醒
+    return this._reminders.filter((reminder) => reminder.tag.toLowerCase() === keyword);
+  }
+
+  /**
+   * Returns a list of reminders with descriptions that match the keyword.
+   * @param keyword - Text to search for in description and tag
+   */
+  private searchDescriptions(keyword: string): Reminder[] {
+    // 篩選出描述中包含關鍵字的提醒
+    return this._reminders.filter((reminder) => reminder.description.toLowerCase().includes(keyword));
+  }
 }