新增google tasks

 /**

 * 將任務新增到 Google Tasks 的預設列表。

 * @param {object} taskData 包含任務資訊的物件,例如 { title: '洗牙', due: '2025-05-06T08:45:00.000Z' }

 * @param {string} token 從 getAuthToken 獲取的 Access Token (需要包含 tasks scope)。

 * @returns {Promise<object>} 解析為創建的任務物件。

 */

async function addTaskToGoogle(taskData, token) {

  // Tasks API 的端點,通常是添加到預設列表 (@default)

  const tasklistId = '@default';

  const apiUrl = `https://www.googleapis.com/tasks/v1/lists/${tasklistId}/tasks`;


  // 準備請求體 (Request Body)

  // 至少需要 title,可以添加 due, notes 等

  const requestBody = {

    title: taskData.title,

    // 如果需要截止時間 (格式很重要!)

// 使用展開語法,只有當 taskData.due 存在時才添加 due 屬性

    ...(taskData.due && { due: taskData.due }), // RFC 3339 UTC timestamp, e.g., '2024-12-31T10:00:00.000Z'

// 同理,只有 taskData.notes 存在時才添加 notes 屬性

    ...(taskData.notes && { notes: taskData.notes }), // 備註

    // 還有 status, parent 等其他欄位可用

  };


  try {

    const response = await fetch(apiUrl, {

      method: 'POST',

      headers: {

        'Authorization': `Bearer ${token}`,

        'Content-Type': 'application/json'

      },

      body: JSON.stringify(requestBody)

    });


    if (!response.ok) {

      const error = await response.json();

      console.error('Error adding task via API:', error);

      // 拋出更詳細的錯誤,或者根據 status code 處理

      throw new Error(`Failed to add task: ${error.error?.message || response.statusText}`);

    }


    const createdTask = await response.json();

    console.log('Task created successfully:', createdTask);

    return createdTask; // 返回創建的任務物件,其中包含 Google 生成的 id 等資訊


  } catch (error) {

    console.error('Error during fetch to add task:', error);

    throw error; // 將錯誤向上拋出,讓調用者處理

  }

}


// --- 如何調用 (在獲取 token 之後) ---

async function handleAddTaskClick(taskTitle, dueDateString) { // dueDateString 需為 RFC 3339 格式

  try {

    // 1. 獲取包含 tasks scope 的 token

    // 注意:如果 scope 變更,需要重新觸發授權流程

    const token = await getAuthToken(true); // 確保 getAuthToken 請求了 'tasks' scope


    // 2. 準備 taskData

    const taskData = {

      title: taskTitle

    };

    if (dueDateString) {

      // 重要:確保 dueDateString 是正確的 RFC 3339 UTC 格式

      // 例如: '2025-05-06T08:45:00.000Z'

      // 如果只有日期,格式是 'YYYY-MM-DD',但 Tasks API 可能需要時間部分 for reminder

      taskData.due = dueDateString;

    }


    // 3. 調用 addTaskToGoogle

    const createdTask = await addTaskToGoogle(taskData, token);


    // 4. (可選) 保存返回的 task ID 等資訊

    const googleTaskId = createdTask.id;

    console.log("Google Task ID:", googleTaskId);

    // saveTaskMapping(myInternalId, googleTaskId);


    alert(`行程(${taskTitle}, ${dueDateString})已成功新增到您的 Google Tasks!`);


  } catch (error) {

    console.error('handleAddTasksClick error:', error);

    alert(`新增鬧鐘失敗: ${error.message}`);

  }

}



// --- 處理時間格式 ---

// 您需要確保傳入的 'due' 是 RFC 3339 UTC 格式

// 例如,從日期時間選擇器獲取時間後轉換:

function convertToRFC3339UTC(date) {

  if (!date instanceof Date) {

    date = new Date(date); // 嘗試轉換

  }

  if (isNaN(date.getTime())) {

    return null; // 無效日期

  }

  // toISOString() 返回的格式就是 RFC 3339,且總是 UTC (結尾是 Z)

  return date.toISOString();

}


// 示例: const dueDate = new Date('2025-05-06T16:45:00+08:00'); // 假設本地時間是 +08:00

// const rfc3339Date = convertToRFC3339UTC(dueDate); // 結果會是 '2025-05-06T08:45:00.000Z'

// handleAddTaskClick("洗牙", rfc3339Date);


留言

這個網誌中的熱門文章

Offscreen Canvas

外部網頁新增 Google 日曆行程(URL模板)

計算 Canvas 文字最大字體