From d7a8bedac14c5b64c0d0e28a935584f4d4213a22 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Thu, 25 Sep 2025 10:30:50 +0000 Subject: [PATCH] Auto commit: 2025-09-25T10:30:50.227Z --- assets/css/custom.css | 120 ++++++++++++++ assets/js/main.js | 90 ++++++++++ index.php | 373 ++++++++++++++++++++++++++++-------------- 3 files changed, 461 insertions(+), 122 deletions(-) create mode 100644 assets/css/custom.css create mode 100644 assets/js/main.js diff --git a/assets/css/custom.css b/assets/css/custom.css new file mode 100644 index 0000000..45825c3 --- /dev/null +++ b/assets/css/custom.css @@ -0,0 +1,120 @@ + +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap'); + +:root { + --primary-color: #4A90E2; + --secondary-color: #50E3C2; + --background-color: #F4F7F9; + --surface-color: #FFFFFF; + --text-color: #333333; + --border-color: #E0E6ED; + --border-radius: 0.5rem; + --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); + --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); +} + +body { + font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + background-color: var(--background-color); + color: var(--text-color); + line-height: 1.5; +} + +.navbar { + background-color: var(--surface-color); + box-shadow: var(--shadow-sm); +} + +.navbar-brand { + font-weight: 700; + color: var(--primary-color) !important; +} + +.container { + max-width: 1140px; +} + +.card { + border: none; + border-radius: var(--border-radius); + box-shadow: var(--shadow-md); + background-color: var(--surface-color); +} + +.card-header { + background-color: transparent; + border-bottom: 1px solid var(--border-color); + font-weight: 600; + padding: 1rem 1.5rem; +} + +.card-body { + padding: 1.5rem; +} + +.form-control, .form-select { + border-radius: var(--border-radius); + border: 1px solid var(--border-color); + padding: 0.75rem 1rem; +} + +.form-control:focus { + border-color: var(--primary-color); + box-shadow: 0 0 0 0.25rem rgba(74, 144, 226, 0.25); +} + +.btn { + border-radius: var(--border-radius); + padding: 0.75rem 1.5rem; + font-weight: 600; + transition: all 0.2s ease-in-out; +} + +.btn-primary { + background-color: var(--primary-color); + border-color: var(--primary-color); +} + +.btn-primary:hover { + opacity: 0.9; +} + +.table { + border-color: var(--border-color); +} + +.table th { + font-weight: 600; + background-color: #F9FAFB; +} + +.table td, .table th { + vertical-align: middle; +} + +.toast-container { + position: fixed; + top: 1rem; + right: 1rem; + z-index: 1090; +} + +.toast { + border-radius: var(--border-radius); + border: none; + box-shadow: var(--shadow-md); +} + +.toast-header { + border-bottom: 1px solid rgba(0,0,0,0.05); +} + +.table .btn-sm { + padding: 0.25rem 0.6rem; +} + +.feather-sm { + width: 16px; + height: 16px; + vertical-align: text-bottom; +} diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..836654d --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1,90 @@ + +document.addEventListener('DOMContentLoaded', function () { + // --- Client-side validation for the add contact form --- + const addContactForm = document.getElementById('addContactForm'); + if (addContactForm) { + addContactForm.addEventListener('submit', function (event) { + if (!validateForm(this)) { + event.preventDefault(); + event.stopPropagation(); + } + }); + } + + // --- Client-side validation for the edit contact form --- + const editContactForm = document.getElementById('editContactForm'); + if (editContactForm) { + editContactForm.addEventListener('submit', function(event) { + if (!validateForm(this)) { + event.preventDefault(); + event.stopPropagation(); + } + }); + } + + // --- Edit Modal Handler --- + const editContactModal = document.getElementById('editContactModal'); + if (editContactModal) { + editContactModal.addEventListener('show.bs.modal', function (event) { + const button = event.relatedTarget; + // Extract info from data-bs-* attributes + const id = button.getAttribute('data-id'); + const name = button.getAttribute('data-name'); + const email = button.getAttribute('data-email'); + const phone = button.getAttribute('data-phone'); + + // Update the modal's content. + const modalTitle = editContactModal.querySelector('.modal-title'); + const contactIdInput = editContactModal.querySelector('#edit_contact_id'); + const nameInput = editContactModal.querySelector('#edit_name'); + const emailInput = editContactModal.querySelector('#edit_email'); + const phoneInput = editContactModal.querySelector('#edit_phone'); + + modalTitle.textContent = 'Edit Contact: ' + name; + contactIdInput.value = id; + nameInput.value = name; + emailInput.value = email; + phoneInput.value = phone; + }); + } + + // --- Toast notification handling --- + const toastEl = document.getElementById('notificationToast'); + if (toastEl) { + const toast = new bootstrap.Toast(toastEl, { delay: 5000 }); + toast.show(); + } + + // --- Feather Icons --- + feather.replace(); +}); + +/** + * Validates a contact form (add or edit). + * @param {HTMLFormElement} form The form element to validate. + * @returns {boolean} True if valid, false otherwise. + */ +function validateForm(form) { + const name = form.querySelector('input[name="name"]'); + const email = form.querySelector('input[name="email"]'); + let isValid = true; + + // Reset invalid states + name.classList.remove('is-invalid'); + email.classList.remove('is-invalid'); + + // Validate Name + if (name.value.trim() === '') { + name.classList.add('is-invalid'); + isValid = false; + } + + // Validate Email + const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + if (email.value.trim() === '' || !emailPattern.test(email.value)) { + email.classList.add('is-invalid'); + isValid = false; + } + + return isValid; +} diff --git a/index.php b/index.php index 6f7ffab..ab4aac9 100644 --- a/index.php +++ b/index.php @@ -1,131 +1,260 @@ exec("CREATE TABLE IF NOT EXISTS contacts ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL, + phone VARCHAR(50), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + )"); + + // Handle POST requests + if ($_SERVER['REQUEST_METHOD'] === 'POST') { + // Add a new contact + if (isset($_POST['add_contact'])) { + $name = trim($_POST['name']); + $email = trim($_POST['email']); + $phone = trim($_POST['phone']); + + if (!empty($name) && !empty($email) && filter_var($email, FILTER_VALIDATE_EMAIL)) { + $stmt = $pdo->prepare("INSERT INTO contacts (name, email, phone) VALUES (?, ?, ?)"); + $stmt->execute([$name, $email, $phone]); + $_SESSION['notification'] = ['type' => 'success', 'message' => 'Contact added successfully!']; + } else { + $_SESSION['notification'] = ['type' => 'danger', 'message' => 'Invalid data. Please check your input.']; + } + } + // Update an existing contact + elseif (isset($_POST['update_contact'])) { + $id = $_POST['contact_id']; + $name = trim($_POST['name']); + $email = trim($_POST['email']); + $phone = trim($_POST['phone']); + + if (!empty($id) && !empty($name) && !empty($email) && filter_var($email, FILTER_VALIDATE_EMAIL)) { + $stmt = $pdo->prepare("UPDATE contacts SET name = ?, email = ?, phone = ? WHERE id = ?"); + $stmt->execute([$name, $email, $phone, $id]); + $_SESSION['notification'] = ['type' => 'success', 'message' => 'Contact updated successfully!']; + } else { + $_SESSION['notification'] = ['type' => 'danger', 'message' => 'Invalid data. Please check your input.']; + } + } + // Delete a contact + elseif (isset($_POST['delete_contact'])) { + $id = $_POST['contact_id']; + if (!empty($id)) { + $stmt = $pdo->prepare("DELETE FROM contacts WHERE id = ?"); + $stmt->execute([$id]); + $_SESSION['notification'] = ['type' => 'info', 'message' => 'Contact deleted.']; + } + } + + header("Location: index.php"); + exit; + } + + // Check for notification from session + if (isset($_SESSION['notification'])) { + $notification = $_SESSION['notification']; + unset($_SESSION['notification']); + } + + // Fetch all contacts + $stmt = $pdo->query("SELECT id, name, email, phone, created_at FROM contacts ORDER BY created_at DESC"); + $contacts = $stmt->fetchAll(); + +} catch (PDOException $e) { + // For a real app, you'd log this error and show a user-friendly message. + $notification = ['type' => 'danger', 'message' => 'Database error: ' . $e->getMessage()]; + $contacts = []; +} ?> - + - - - New Style - - - - + + + CRM - Contact Management + + + + + + + + + + + + + + -
-
-

Analyzing your requirements and generating your website…

-
- Loading… -
-

AI is collecting your requirements and applying the first changes.

-

This page will update automatically as the plan is implemented.

-

Runtime: PHP — UTC

+ + + +
+
-
- + + + + +
+
+ +
+
+
+

Add New Contact

+
+
+
+ +
+ + +
Please enter a name.
+
+
+ + +
Please enter a valid email address.
+
+
+ + +
+
+ +
+
+
+
+
+ + +
+
+
+

Contact List

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameEmailPhoneDate AddedActions
No contacts yet. Add one to get started!
+ +
+ + + +
+
+
+
+
+
+
+ + + +
+ + + + + + - + \ No newline at end of file