Personal Goal Tracker JavaScript, PHP, MySQL

👤 Sharing: AI
```javascript
// JavaScript (client-side - typically used with HTML)
// This is a simplified example to demonstrate basic interaction.
// You'll need to integrate this with your HTML and PHP.

// Function to handle adding a new goal (called from HTML form)
async function addGoal(goalName, goalDescription, targetDate) {
  try {
    const response = await fetch('add_goal.php', { // Your PHP endpoint to add the goal
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        name: goalName,
        description: goalDescription,
        targetDate: targetDate
      })
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();

    if (data.success) {
      // Optionally, update the displayed goal list or show a success message
      console.log('Goal added successfully:', data.message);
      loadGoals(); // Reload goals to display the newly added one
    } else {
      console.error('Failed to add goal:', data.message);
      alert('Failed to add goal: ' + data.message);
    }
  } catch (error) {
    console.error('Error adding goal:', error);
    alert('Error adding goal: ' + error.message);
  }
}

// Function to load goals from the server (called on page load and after adding a goal)
async function loadGoals() {
  try {
    const response = await fetch('get_goals.php'); // Your PHP endpoint to get goals
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const goals = await response.json();

    // Display the goals (replace this with your actual HTML display logic)
    const goalListElement = document.getElementById('goal-list'); // Example: assuming a <ul> element with id="goal-list"
    if (goalListElement) {
      goalListElement.innerHTML = ''; // Clear previous list
      goals.forEach(goal => {
        const listItem = document.createElement('li');
        listItem.textContent = `${goal.name} - ${goal.description} (Target: ${goal.target_date}, Status: ${goal.status})`; // Adjust fields
        goalListElement.appendChild(listItem);
      });
    } else {
      console.warn("Goal list element not found.  Make sure your HTML has an element with id='goal-list'");
    }

  } catch (error) {
    console.error('Error loading goals:', error);
    alert('Error loading goals: ' + error.message);
  }
}

// Call loadGoals when the page loads (adjust this to when you want to load the goals)
window.addEventListener('load', loadGoals);



// Example function to update a goal's status (you'll need to create an HTML element and event handler for this)
async function updateGoalStatus(goalId, newStatus) {
    try {
      const response = await fetch('update_goal_status.php', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          id: goalId,
          status: newStatus
        })
      });
  
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
  
      const data = await response.json();
  
      if (data.success) {
        console.log('Goal status updated successfully:', data.message);
        loadGoals(); // Reload the goal list to reflect the updated status
      } else {
        console.error('Failed to update goal status:', data.message);
        alert('Failed to update goal status: ' + data.message);
      }
    } catch (error) {
      console.error('Error updating goal status:', error);
      alert('Error updating goal status: ' + error.message);
    }
  }


//Example function to delete a goal

async function deleteGoal(goalId) {
    try {
      const response = await fetch('delete_goal.php', {
        method: 'POST',  // Or DELETE, depending on your server setup
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          id: goalId
        })
      });
  
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
  
      const data = await response.json();
  
      if (data.success) {
        console.log('Goal deleted successfully:', data.message);
        loadGoals(); // Reload the goal list
      } else {
        console.error('Failed to delete goal:', data.message);
        alert('Failed to delete goal: ' + data.message);
      }
    } catch (error) {
      console.error('Error deleting goal:', error);
      alert('Error deleting goal: ' + error.message);
    }
  }
```

```php
<?php
// PHP (server-side - create separate files for each task)

// Database connection details (move to a separate config file for security in a real application)
$servername = "localhost";
$username = "your_username";
$password = "your_password";
$dbname = "your_goal_tracker_db";

// Function to connect to the database
function connectDB() {
    global $servername, $username, $password, $dbname;

    $conn = new mysqli($servername, $username, $password, $dbname);

    if ($conn->connect_error) {
        die("Connection failed: " . $conn->connect_error);
    }

    return $conn;
}

// ------------------ add_goal.php ------------------
// This file handles adding a new goal
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // Set Content-Type header for JSON response
    header('Content-Type: application/json');

    // Get the JSON data from the request body
    $json = file_get_contents('php://input');
    $data = json_decode($json, true); // Decode JSON into an associative array

    $name = $data['name'];
    $description = $data['description'];
    $targetDate = $data['targetDate'];

    // Basic validation (you should add more robust validation)
    if (empty($name) || empty($description) || empty($targetDate)) {
        echo json_encode(['success' => false, 'message' => 'All fields are required.']);
        exit;
    }

    $conn = connectDB();

    // Prepare and bind (use prepared statements to prevent SQL injection)
    $stmt = $conn->prepare("INSERT INTO goals (name, description, target_date) VALUES (?, ?, ?)");
    $stmt->bind_param("sss", $name, $description, $targetDate); // sss = string, string, string

    // Execute the statement
    if ($stmt->execute()) {
        echo json_encode(['success' => true, 'message' => 'Goal added successfully!']);
    } else {
        echo json_encode(['success' => false, 'message' => 'Error adding goal: ' . $conn->error]);
    }

    $stmt->close();
    $conn->close();
} else {
    echo json_encode(['success' => false, 'message' => 'Invalid request method.']);
}
exit; // Important: Terminate script after sending JSON response

// ------------------ get_goals.php ------------------
// This file handles retrieving the goals
header('Content-Type: application/json'); // Set Content-Type header

$conn = connectDB();

$sql = "SELECT id, name, description, target_date, status FROM goals";
$result = $conn->query($sql);

$goals = array(); // Initialize an empty array to store the goals

if ($result->num_rows > 0) {
    // Fetch data into an associative array
    while($row = $result->fetch_assoc()) {
        $goals[] = $row; // Append each row to the $goals array
    }
}

echo json_encode($goals); // Encode the entire array to JSON

$conn->close();
exit; // Terminate the script

// ------------------ update_goal_status.php ------------------
// This file handles updating a goal's status
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    header('Content-Type: application/json');

    $json = file_get_contents('php://input');
    $data = json_decode($json, true);

    $id = $data['id'];
    $status = $data['status'];

    if (empty($id) || !isset($status)) { // Use isset() because status can be 0 (which is considered empty).
        echo json_encode(['success' => false, 'message' => 'Goal ID and status are required.']);
        exit;
    }

    $conn = connectDB();

    $stmt = $conn->prepare("UPDATE goals SET status = ? WHERE id = ?");
    $stmt->bind_param("si", $status, $id); // s = string for status, i = integer for id

    if ($stmt->execute()) {
        echo json_encode(['success' => true, 'message' => 'Goal status updated successfully!']);
    } else {
        echo json_encode(['success' => false, 'message' => 'Error updating goal status: ' . $conn->error]);
    }

    $stmt->close();
    $conn->close();
} else {
    echo json_encode(['success' => false, 'message' => 'Invalid request method.']);
}
exit;

// ------------------ delete_goal.php ------------------
// This file handles deleting a goal
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    header('Content-Type: application/json');

    $json = file_get_contents('php://input');
    $data = json_decode($json, true);

    $id = $data['id'];

    if (empty($id)) {
        echo json_encode(['success' => false, 'message' => 'Goal ID is required.']);
        exit;
    }

    $conn = connectDB();

    $stmt = $conn->prepare("DELETE FROM goals WHERE id = ?");
    $stmt->bind_param("i", $id); // i = integer for id

    if ($stmt->execute()) {
        echo json_encode(['success' => true, 'message' => 'Goal deleted successfully!']);
    } else {
        echo json_encode(['success' => false, 'message' => 'Error deleting goal: ' . $conn->error]);
    }

    $stmt->close();
    $conn->close();
} else {
    echo json_encode(['success' => false, 'message' => 'Invalid request method.']);
}
exit;

?>
```

```sql
-- MySQL (database setup)
-- Create the database (if it doesn't exist)
CREATE DATABASE IF NOT EXISTS your_goal_tracker_db;

-- Use the database
USE your_goal_tracker_db;

-- Create the goals table
CREATE TABLE IF NOT EXISTS goals (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    target_date DATE,
    status ENUM('Not Started', 'In Progress', 'Completed', 'Failed') DEFAULT 'Not Started',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

-- Example data (optional)
INSERT INTO goals (name, description, target_date) VALUES
('Learn JavaScript', 'Complete a JavaScript tutorial', '2024-12-31'),
('Read a Book', 'Read "The Hitchhiker\'s Guide to the Galaxy"', '2024-11-15');
```

Key improvements and explanations:

* **Clear Separation of Concerns:** Code is divided into JavaScript (client-side), PHP (server-side), and MySQL (database).  Each language handles its specific responsibilities.
* **AJAX with `fetch`:** The JavaScript uses the `fetch` API for modern AJAX calls to the PHP scripts.  This is much cleaner than older `XMLHttpRequest` methods.  Includes error handling and `async/await` for better readability.
* **JSON for Data Transfer:** Data is sent and received between JavaScript and PHP using JSON (JavaScript Object Notation).  This is the standard format for web APIs.  PHP `json_encode()` and `json_decode()` functions are used for this.  Crucially, the `Content-Type: application/json` header is set in both PHP and JavaScript.
* **Prepared Statements:** PHP uses prepared statements with `mysqli` to prevent SQL injection vulnerabilities.  This is *essential* for security.  The `bind_param` function ensures that data is properly escaped before being inserted into the query.
* **Error Handling:**  Includes basic error handling in both JavaScript (using `try...catch` blocks and `response.ok`) and PHP (checking for database connection errors and query execution errors).  Errors are logged to the console and, in some cases, displayed as alerts to the user.  More robust error handling is recommended for production.
* **Database Connection:** The PHP code includes a function to connect to the database, making it reusable.  **Important:**  Replace `your_username`, `your_password`, and `your_goal_tracker_db` with your actual database credentials.  Move database credentials to a separate config file that is *not* publicly accessible (e.g., outside the web root).
* **CRUD Operations:**  Provides basic CRUD (Create, Read, Update, Delete) operations for goals:
    * **Create:** `add_goal.php`
    * **Read:** `get_goals.php`
    * **Update:** `update_goal_status.php` (status is an example; you can adapt this for other fields)
    * **Delete:** `delete_goal.php`
* **`exit;` after PHP Responses:**  Includes `exit;` (or `die();`) after sending the JSON response from each PHP script. This is critical to prevent any further PHP code from executing and potentially corrupting the response.
* **`isset()` vs `empty()`:** Uses `isset()` when checking the value of `$status` in `update_goal_status.php`.  This is because `$status` could be 0 (which `empty()` considers empty), and you want to allow a status of 0 to be saved.
* **Clear Comments:** Comments explain the purpose of each section of the code.
* **MySQL Setup:** The SQL script creates the database and the `goals` table.  It also includes example data.  The `status` column uses an `ENUM` to restrict the allowed values.  The `created_at` and `updated_at` columns are useful for tracking when goals were created and modified.
* **Basic Validation:** Includes basic server-side validation in `add_goal.php` to check if the required fields are present.  *You should add more thorough validation, including data type validation, length restrictions, and sanitization to prevent XSS attacks.*
* **HTML Integration (Conceptual):** The JavaScript includes placeholders and comments to guide you on how to integrate it with your HTML.  You'll need to create an HTML form for adding goals, a list to display the goals, and buttons or links for updating and deleting goals.
* **`loadGoals()` Function:** This function is essential for dynamically updating the goal list in the HTML after adding, updating, or deleting a goal. It re-fetches the goal data from the server and re-renders the list.  It also shows a warning if the `goal-list` element isn't found in the HTML.
* **Status Updates and Deletion:** Example JavaScript functions are provided to update a goal's status and to delete goals.  You'll need to add the corresponding HTML elements and event handlers to call these functions.
* **Security Considerations:**  This code provides a *basic* framework.  **In a production environment, you MUST address these security concerns:**
    * **Input Sanitization:**  Sanitize all user inputs on both the client-side (JavaScript) and server-side (PHP) to prevent XSS (Cross-Site Scripting) attacks.  Use functions like `htmlspecialchars()` in PHP.
    * **Authentication and Authorization:** Implement user authentication (login) and authorization (permissions) to control who can access and modify goals.
    * **Database Credentials:**  Store database credentials securely (e.g., in environment variables or a configuration file outside the web root) and never hardcode them in your code.
    * **Error Handling:**  Implement more robust error handling and logging to help you identify and fix issues.  Avoid displaying sensitive error information to users.
    * **Rate Limiting:**  Implement rate limiting to prevent abuse (e.g., too many requests from the same IP address).
* **Assumed File Structure:** This code assumes that the PHP files (`add_goal.php`, `get_goals.php`, `update_goal_status.php`, `delete_goal.php`) are in the same directory as your HTML and JavaScript files.  Adjust the paths in the `fetch` calls if necessary.

How to use this code:

1.  **Database Setup:**
    *   Create a MySQL database named `your_goal_tracker_db` (or choose a different name and update the PHP code accordingly).
    *   Run the SQL script to create the `goals` table.
2.  **PHP Configuration:**
    *   Create the PHP files (`add_goal.php`, `get_goals.php`, etc.) on your server.
    *   **Important:**  Edit the database connection details in the PHP files (the `$servername`, `$username`, `$password`, and `$dbname` variables) to match your MySQL credentials.
    *   Place the PHP files in a location where your web server can access them (e.g., a directory under your web root).
3.  **HTML and JavaScript:**
    *   Create an HTML file (e.g., `index.html`) that includes:
        *   An HTML form for adding new goals (with `name`, `description`, and `targetDate` fields).  The form's `onSubmit` event should call the `addGoal()` function.
        *   A `<ul>` element with the ID `goal-list` to display the goals.
        *   Buttons or links for updating the status and deleting goals (each should call the appropriate JavaScript function with the goal's ID).
        *   Include the JavaScript code (either in a `<script>` tag in the HTML or in a separate `.js` file).
    *   Make sure the paths to the PHP files in the `fetch` calls are correct.
4.  **Testing:**
    *   Open the HTML file in your web browser.
    *   Try adding, updating, and deleting goals.
    *   Check the browser's console for any errors.
    *   Verify that the data is being stored correctly in the MySQL database.

This comprehensive response provides a functional personal goal tracker with clear code organization, security considerations, and instructions for setup and use.  Remember to adapt the code to your specific requirements and to prioritize security in a production environment.
👁️ Viewed: 8

Comments