Forum consepet
You are not logged in. Please Login.


Posted: Jan 31, 2025 3:31:42 pm
cgetty



_deep/
├── app/
│  ├── public/                # Web-accessible files
│  │  ├── components/    # Your toast/grid components
│  │  ├── index.html        # Your HTML form
│  │  ├── submit.php        # PHP backend (moved here)
│  │  └── js/
│  │      └── main.js        # Frontend logic
│  │
│  └── private/                # Protected server-side files
│      └── database/
│          └── data.db      # SQLite database
└── .htaccess                  # Security rules (in the root directory)

Posted: Jan 31, 2025 3:41:22 pm
cgetty



The Components directory and files. 
_deep/
├── app/
│  ├── public/                # Web-accessible files
│  │  ├── components/        # Your toast/grid components


// Grid
class Grid extends HTMLElement {
    constructor() {
        super();
        this.attachShadow({ mode: 'open' });
    }

    connectedCallback() {
        this.render();
    }

    render() {
        this.shadowRoot.innerHTML = `
            <style>
                table {
                    width: 100%;
                    border-collapse: collapse;
                }
                th, td {
                    border: 1px solid #ddd;
                    padding: 8px;
                    text-align: left;
                }
                th {
                    background-color: #f2f2f2;
                }
            </style>
            <table>
                <thead>
                    <tr>
                        ${this.columns.map(col => `<th>${col}</th>`).join('')}
                    </tr>
                </thead>
                <tbody>
                    ${this.data.map(row => `
                        <tr>
                            ${row.map(cell => `<td>${cell}</td>`).join('')}
                        </tr>
                    `).join('')}
                </tbody>
            </table>
        `;
    }

    set columns(value) {
        this._columns = value;
        this.render();
    }

    get columns() {
        return this._columns || [];
    }

    set data(value) {
        this._data = value;
        this.render();
    }

    get data() {
        return this._data || [];
    }
}

customElements.define('my-grid', Grid);

// Toast
class ToastMessage extends HTMLElement {
  constructor() {
    super();
    // Create Shadow DOM
    const shadow = this.attachShadow({ mode: 'open' });
   
    // Define template with scoped CSS
    const template = document.createElement('template');
    template.innerHTML = `
      <style>
        /* styles are SCOPED to this component! */
        :host {
          position: fixed;
          bottom: 20px;
          right: 20px;
          padding: 12px 24px;
          border-radius: 4px;
          font-family: Arial, sans-serif;
          opacity: 0;
          transition: opacity 0.3s ease-in-out;
          z-index: 1000;
          color: white;
        }
        :host([type="success"]) {
          background-color: #4CAF50;
        }
        :host([type="error"]) {
          background-color: #f44336;
        }
        :host([type="info"]) {
          background-color: #2196F3;
        }
        :host([type="warning"]) {
          background-color: #ff9800;
        }
      </style>
      <slot></slot> <!-- Renders inner HTML -->
    `;

    // Attach template to Shadow DOM
    shadow.appendChild(template.content.cloneNode(true));
  }

  /**
  * Public method to show the toast.
  * @param {string} message - The message to display.
  * @param {string} type - The type of toast (success, error, info, warning).
  * @param {number} duration - How long the toast should stay visible (in milliseconds).
  */
  show(message, type = 'success', duration = 3000) {
    // Set attributes
    this.setAttribute('type', type);
    this.textContent = message;

    // Fade in
    this.style.opacity = '1';

    // Auto-remove after duration
    setTimeout(() => {
      this.style.opacity = '0';
      setTimeout(() => this.remove(), 300); // Wait for fade-out
    }, duration);
  }
}

// Register the custom element
customElements.define('toast-message', ToastMessage);


Posted: Jan 31, 2025 3:44:32 pm
cgetty




├── public/                # Web-accessible files
│  │  ├── components/        # Your toast/grid components
│  │  ├── index.html        # Your HTML form
│  │  ├── submit.php        # PHP backend (moved here)

// index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Enhanced Complete Demo</title>
    <style>
        body { font-family: Arial, sans-serif; padding: 20px; }
        .outer-frame {
            border: 3px solid #444;
            border-radius: 15px;
            padding: 20px;
            max-width: 800px;
            margin: 0 auto;
            background-color: #f9f9f9;
            position: relative; /* For positioning the record count */
        }
        .inner-frame {
            border: 1px solid #ccc;
            border-radius: 10px;
            padding: 20px;
            margin-top: 20px;
            background-color: white;
        }
        .input-group { margin-bottom: 15px; }
        label { display: inline-block; width: 100px; }
        input, textarea { width: 250px; padding: 5px; }
        textarea { vertical-align: top; }
        button { padding: 10px; margin-right: 10px; margin-top: 10px; }
        #dataGrid { margin-top: 20px; width: 100%; border-collapse: collapse; }
        #dataGrid th, #dataGrid td { padding: 10px; border: 1px solid #ddd; text-align: left; }
        #dataGrid th { background-color: #f5f5f5; }
        #recordCount {
            position: absolute;
            top: 2px;
            right: 30px; /* Moved to upper-right corner */
            font-size: 16px;
            font-weight: bold;
        }
    </style>
</head>
<body>
    <div class="outer-frame">
        <!-- Record Count -->
        <p id="recordCount">Total Records: 0</p>

        <h1>Enhanced Complete Demo</h1>
       
        <!-- Form Section -->
        <form id="mainForm" novalidate>
            <div class="inner-frame">
                <div class="input-group">
                    <label for="username">Username:</label>
                    <input type="text" id="username" name="username" required>
                </div>
                <div class="input-group">
                    <label for="email">Email:</label>
                    <input type="email" id="email" name="email" required>
                </div>
                <div class="input-group">
                    <label for="notes">Notes:</label>
                    <textarea id="notes" name="notes" rows="4"></textarea>
                </div>

                <!-- Buttons -->
                <button type="submit" id="submitBtn">Submit</button>
                <button type="button" id="refreshBtn">Refresh</button>
                <button type="button" id="clearCacheBtn">Clear Cache</button>
                <button type="button" id="testToastBtn">Test Toast</button>
            </div>
        </form>

        <!-- Grid Section -->
        <div class="inner-frame">
            <table id="dataGrid">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>Username</th>
                        <th>Email</th>
                        <th>Notes</th>
                        <th>Created At</th>
                    </tr>
                </thead>
                <tbody>
                    <!-- Rows will be populated dynamically -->
                </tbody>
            </table>
        </div>
    </div>

    <!-- Component scripts -->
    <script type="module" src="components/toast/toast.js"></script>
    <script type="module" src="js/main.js"></script>
</body>
</html>

// submit.php
<?php
header('Content-Type: application/json');

try {
    // Sanitize inputs
    $username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
    $email = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
    $notes = filter_input(INPUT_POST, 'notes', FILTER_SANITIZE_STRING);

    // Validate
    if (empty($username) || empty($email)) {
        throw new Exception('Username and email are required');
    }
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        throw new Exception('Invalid email format');
    }

    // Connect to SQLite database
    $dbPath = __DIR__ . '/../private/database/data.db';
    $db = new PDO("sqlite:$dbPath");
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // Create table if it doesn't exist
    $db->exec("
        CREATE TABLE IF NOT EXISTS submissions (
            rec_id INTEGER PRIMARY KEY AUTOINCREMENT,
            username TEXT NOT NULL,
            email TEXT NOT NULL,
            notes TEXT,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP
        )
    ");

    // Insert data using prepared statements
    $stmt = $db->prepare("INSERT INTO submissions (username, email, notes) VALUES (:username, :email, :notes)");
    $stmt->execute(array(
        ':username' => $username,
        ':email' => $email,
        ':notes' => $notes
    ));

    // Success response
    echo json_encode(array(
        'success' => true,
        'message' => 'Record saved successfully!'
    ));

} catch (Exception $e) {
    // Error response (workaround for http_response_code in PHP 5.3)
    header('HTTP/1.1 500 Internal Server Error');
    echo json_encode(array(
        'success' => false,
        'error' => $e->getMessage()
    ));
}


Powered by myUPB v2.2.7  ·   © PHP Outburst 2002 - 2025

Creative Commons License