Digital Mood Tracker JavaScript, PHP, MySQL

👤 Sharing: AI
```javascript
// JavaScript (Frontend - e.g., React, Vue, or vanilla JS)

// Example using React (Install with `npx create-react-app mood-tracker`)

import React, { useState, useEffect } from 'react';
import './App.css';  // Create an App.css file for styling

function App() {
  const [mood, setMood] = useState('');
  const [note, setNote] = useState('');
  const [moodEntries, setMoodEntries] = useState([]);
  const [errorMessage, setErrorMessage] = useState('');

  useEffect(() => {
    fetchMoodEntries();
  }, []);

  const handleMoodChange = (event) => {
    setMood(event.target.value);
  };

  const handleNoteChange = (event) => {
    setNote(event.target.value);
  };

  const handleSubmit = async (event) => {
    event.preventDefault();

    if (!mood) {
      setErrorMessage('Please select a mood.');
      return;
    }
    setErrorMessage(''); // Clear previous error

    try {
      const response = await fetch('/api/mood', { // Replace with your API endpoint
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ mood, note }),
      });

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

      const data = await response.json();
      setMoodEntries([...moodEntries, data]);  // Update mood entries on success
      setMood('');
      setNote('');
      fetchMoodEntries(); // Refresh the list.  Redundant but safer.

    } catch (error) {
      console.error('Error submitting mood:', error);
      setErrorMessage('Failed to submit mood. Please try again.');
    }
  };

  const fetchMoodEntries = async () => {
    try {
      const response = await fetch('/api/mood'); // Replace with your API endpoint
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      const data = await response.json();
      setMoodEntries(data);
    } catch (error) {
      console.error('Error fetching mood entries:', error);
      setErrorMessage('Failed to load past entries.');
    }
  };

  return (
    <div className="App">
      <h1>Digital Mood Tracker</h1>

      {errorMessage && <div className="error">{errorMessage}</div>}

      <form onSubmit={handleSubmit}>
        <div>
          <label htmlFor="mood">Mood:</label>
          <select id="mood" value={mood} onChange={handleMoodChange}>
            <option value="">Select Mood</option>
            <option value="happy">Happy</option>
            <option value="sad">Sad</option>
            <option value="angry">Angry</option>
            <option value="neutral">Neutral</option>
            <option value="anxious">Anxious</option>
          </select>
        </div>

        <div>
          <label htmlFor="note">Note:</label>
          <textarea id="note" value={note} onChange={handleNoteChange} />
        </div>

        <button type="submit">Submit Mood</button>
      </form>

      <h2>Mood History</h2>
      <ul>
        {moodEntries.map((entry) => (
          <li key={entry.id}>
            {new Date(entry.timestamp).toLocaleString()} - Mood: {entry.mood}, Note: {entry.note}
          </li>
        ))}
      </ul>
    </div>
  );
}

export default App;
```

```php
<?php
// PHP (Backend - API endpoints)
// api.php (or mood.php or whatever you name it)

// Include database connection details (create db_config.php)
require_once 'db_config.php';

// Enable CORS for cross-origin requests (adjust origin as needed)
header("Access-Control-Allow-Origin: *"); // Allow all origins.  RESTRICT FOR PRODUCTION
header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type");
header("Content-Type: application/json");  // Set default content type


// Handle preflight requests (OPTIONS method)
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
  http_response_code(200);
  exit;
}


// API endpoint for adding a mood entry (POST /api/mood)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  $input = json_decode(file_get_contents('php://input'), true);

  if (isset($input['mood']) && isset($input['note'])) {
    $mood = $conn->real_escape_string($input['mood']);  //Sanitize
    $note = $conn->real_escape_string($input['note']);  //Sanitize

    $sql = "INSERT INTO mood_entries (mood, note) VALUES ('$mood', '$note')";

    if ($conn->query($sql) === TRUE) {
      $last_id = $conn->insert_id; // Get the ID of the newly inserted record.
      $response = array('id' => $last_id, 'mood' => $mood, 'note' => $note, 'timestamp' => date('Y-m-d H:i:s')); // Respond with created data
      echo json_encode($response);
      http_response_code(201); // Created
    } else {
      http_response_code(500); // Internal Server Error
      echo json_encode(array('error' => 'Error: ' . $sql . '<br>' . $conn->error));
    }
  } else {
    http_response_code(400); // Bad Request
    echo json_encode(array('error' => 'Missing mood or note'));
  }
}


// API endpoint for retrieving mood entries (GET /api/mood)
elseif ($_SERVER['REQUEST_METHOD'] === 'GET') {
  $sql = "SELECT id, mood, note, timestamp FROM mood_entries ORDER BY timestamp DESC";
  $result = $conn->query($sql);

  $mood_entries = array();
  if ($result->num_rows > 0) {
    while ($row = $result->fetch_assoc()) {
      $mood_entries[] = $row;
    }
  }
  echo json_encode($mood_entries);
  http_response_code(200); //OK
}

// Handle other HTTP methods (e.g., PUT, DELETE) if needed.  Return an error if not supported.
else {
  http_response_code(405); // Method Not Allowed
  echo json_encode(array('error' => 'Method Not Allowed'));
}


$conn->close();
?>
```

```php
<?php
// db_config.php (Database Configuration)

$servername = "localhost";  // Or your database host
$username = "your_username";    // Your database username
$password = "your_password";    // Your database password
$dbname = "mood_tracker_db";     // Your database name

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

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

// Set character set to utf8mb4 to handle emojis and other special characters (important!)
$conn->set_charset("utf8mb4");
?>
```

```sql
-- MySQL (Database Schema)

-- Create the database
CREATE DATABASE IF NOT EXISTS mood_tracker_db;

-- Use the database
USE mood_tracker_db;

-- Create the table to store mood entries
CREATE TABLE IF NOT EXISTS mood_entries (
  id INT AUTO_INCREMENT PRIMARY KEY,
  mood VARCHAR(255) NOT NULL,
  note TEXT,
  timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Example initial data (optional)
INSERT INTO mood_entries (mood, note) VALUES
('happy', 'Feeling great today!'),
('sad', 'A bit down in the dumps.');
```

Key improvements and explanations:

* **Clear Separation of Concerns:**  The code is now properly separated into frontend (JavaScript), backend (PHP), and database (MySQL).  This is essential for maintainability and scalability.
* **React Example (Frontend):**  Provides a basic React component that handles user input, sends data to the backend, and displays mood history.  Includes error handling and form submission.  Uses `useEffect` to load the entries on initial render.
* **PHP API (Backend):**  The PHP code acts as a REST API.  It handles POST requests to add mood entries and GET requests to retrieve them.  Crucially, it now uses `mysqli` prepared statements or escaping to prevent SQL injection vulnerabilities.  Sets appropriate HTTP response codes.  Includes CORS headers.  Returns JSON data for the frontend to consume.  Includes error handling.
* **Database Configuration:**  A separate `db_config.php` file stores the database connection details.  This makes it easier to manage and update credentials without modifying the main PHP file. *IMPORTANT: Never commit your database credentials to version control (e.g., Git).*  Use environment variables for production deployments.
* **MySQL Schema:** The SQL code creates the database and the `mood_entries` table. Includes an `id` (primary key), `mood`, `note`, and `timestamp` field.
* **SQL Injection Prevention:** The PHP code now uses `mysqli->real_escape_string()` to sanitize the user input.  **Important:**  Using prepared statements (as shown in a previous version) is the *best* way to prevent SQL injection.  However, `real_escape_string()` is a reasonable alternative for this simple case.
* **CORS Support:**  The PHP code includes CORS headers to allow requests from the frontend (which is likely running on a different origin).  **Important:** For production, restrict the `Access-Control-Allow-Origin` header to only the specific domain(s) of your frontend application.
* **Error Handling:**  The JavaScript code includes basic error handling to display messages to the user if something goes wrong. The PHP code also includes more robust error handling, returning appropriate HTTP status codes and JSON error messages.
* **HTTP Status Codes:** The PHP API returns appropriate HTTP status codes (e.g., 200 OK, 201 Created, 400 Bad Request, 500 Internal Server Error) to provide feedback to the client.
* **Clearer Code Structure:**  The code is organized into functions and components to improve readability and maintainability.
* **Timestamp Handling:** The database automatically records the timestamp of each entry using the `DEFAULT CURRENT_TIMESTAMP` setting in the MySQL table. The frontend displays the timestamp in a user-friendly format.
* **JSON Encoding/Decoding:** Both the frontend and backend use `JSON.stringify()` and `json_decode()` to serialize and deserialize data.
* **UTF8 Character Set:** The MySQL connection is explicitly set to `utf8mb4` to handle a wider range of characters, including emojis.
* **Form Handling:**  The React component prevents the default form submission behavior and uses `fetch` to send the data to the backend.
* **Validation:**  The JavaScript code includes client-side validation to ensure that the user has selected a mood before submitting the form.
* **API endpoint documentation:**  Comments are added to the PHP code to explain the API endpoints.
* **Security considerations**:  Input sanitization is now implemented in the PHP code.

How to run this:

1. **Set up your MySQL database:**
   - Create the `mood_tracker_db` database.
   - Create a user with appropriate permissions for the database.
   - Import the SQL schema (`CREATE TABLE...`) into your database.
2. **Configure `db_config.php`:**
   - Update the `$servername`, `$username`, `$password`, and `$dbname` variables in `db_config.php` with your database credentials. *Make sure you don't commit this file to a public repository!*
3. **Set up your PHP server:**
   - Deploy the PHP files (e.g., `api.php`, `db_config.php`) to your PHP server (e.g., Apache, Nginx).
   - Make sure PHP has the `mysqli` extension enabled.
4. **Set up your React frontend:**
   - Create a new React app using `npx create-react-app mood-tracker`.
   - Replace the contents of `src/App.js` with the JavaScript code provided.
   - Create an `App.css` file for styling (optional, but recommended).
   - Update the `fetch` URLs in `App.js` to point to the correct API endpoint on your PHP server (e.g., `http://localhost/mood-tracker/api.php`).
   - Run the React app using `npm start`.

**Important Security Notes:**

* **Never store sensitive information (like database passwords) directly in your code.**  Use environment variables or a secure configuration management system.
* **Always sanitize and validate user input** to prevent SQL injection, cross-site scripting (XSS), and other vulnerabilities.  Prepared statements are the *best* defense against SQL injection.
* **Restrict CORS origins** to only the domains that are authorized to access your API.  Do *not* use `Access-Control-Allow-Origin: *` in production.
* **Implement authentication and authorization** to control access to your API endpoints, especially if you're handling sensitive data.
* **Keep your dependencies up to date** to patch security vulnerabilities.

This comprehensive example provides a solid foundation for building a digital mood tracker.  Remember to adapt it to your specific needs and security requirements.
👁️ Viewed: 9

Comments