diff --git a/add_contact.php b/add_contact.php
new file mode 100644
index 0000000..23fd65e
--- /dev/null
+++ b/add_contact.php
@@ -0,0 +1,76 @@
+prepare("INSERT INTO contacts (name, company, email, phone, source, tags) VALUES (?, ?, ?, ?, ?, ?)");
+ $stmt->execute([$name, $company, $email, $phone, $source, $tags]);
+ header("Location: index.php?success=1");
+ exit();
+ } catch (PDOException $e) {
+ $error_message = "Error: " . $e->getMessage();
+ }
+ }
+}
+
+include 'header.php';
+?>
+
+
+
+
diff --git a/add_deal.php b/add_deal.php
new file mode 100644
index 0000000..b967175
--- /dev/null
+++ b/add_deal.php
@@ -0,0 +1,86 @@
+query("SELECT id, name FROM contacts ORDER BY name ASC")->fetchAll();
+
+$deal_stages = ['Lead', 'Qualified', 'Proposal', 'Won', 'Lost'];
+
+if ($_SERVER["REQUEST_METHOD"] == "POST") {
+ $title = trim($_POST['title']);
+ $value = trim($_POST['value']);
+ $stage = trim($_POST['stage']);
+ $close_date = trim($_POST['close_date']);
+ $contact_id = trim($_POST['contact_id']);
+
+ if (empty($title) || empty($value) || empty($stage) || empty($contact_id)) {
+ $error_message = "Title, Value, Stage, and Contact are required fields.";
+ } elseif (!is_numeric($value)) {
+ $error_message = "Deal value must be a number.";
+ } else {
+ try {
+ $stmt = db()->prepare("INSERT INTO deals (title, value, stage, close_date, contact_id) VALUES (?, ?, ?, ?, ?)");
+ $stmt->execute([$title, $value, $stage, $close_date, $contact_id]);
+ header("Location: index.php?success_deal=1");
+ exit();
+ } catch (PDOException $e) {
+ $error_message = "Error: " . $e->getMessage();
+ }
+ }
+}
+
+include 'header.php';
+?>
+
+
+
+
diff --git a/assets/css/custom.css b/assets/css/custom.css
new file mode 100644
index 0000000..c2fe97d
--- /dev/null
+++ b/assets/css/custom.css
@@ -0,0 +1,37 @@
+/* Add your custom styles here */
+body {
+ background-color: #f8f9fa;
+}
+
+.navbar {
+ margin-bottom: 2rem;
+}
+
+.card {
+ box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
+}
+
+/* Dashboard KPI cards */
+.card-text.fs-4 {
+ font-weight: 600;
+}
+
+/* Kanban Board Styles */
+.kanban-board .card-header {
+ font-weight: 600;
+}
+
+.kanban-board .card-body {
+ min-height: 400px;
+ overflow-y: auto;
+ background-color: #f4f6f9;
+}
+
+.kanban-board .card-body .card {
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+ transition: box-shadow 0.2s ease-in-out;
+}
+
+.kanban-board .card-body .card:hover {
+ box-shadow: 0 4px 8px rgba(0,0,0,0.15);
+}
diff --git a/assets/js/main.js b/assets/js/main.js
new file mode 100644
index 0000000..52fef2d
--- /dev/null
+++ b/assets/js/main.js
@@ -0,0 +1 @@
+// Add your custom scripts here
diff --git a/contacts.php b/contacts.php
new file mode 100644
index 0000000..689e1fe
--- /dev/null
+++ b/contacts.php
@@ -0,0 +1,97 @@
+ '`name` ASC',
+ 'name_desc' => '`name` DESC',
+ 'company_asc' => '`company` ASC',
+ 'company_desc' => '`company` DESC',
+ 'created_at_asc' => '`created_at` ASC',
+ 'created_at_desc' => '`created_at` DESC',
+];
+$order_by = $sort_options[$sort] ?? '`created_at` DESC';
+
+try {
+ $pdo = db();
+ $search_term = "%$search%";
+
+ $stmt = $pdo->prepare("SELECT * FROM contacts WHERE name LIKE :search OR company LIKE :search OR email LIKE :search ORDER BY $order_by");
+ $stmt->bindParam(':search', $search_term);
+ $stmt->execute();
+ $contacts = $stmt->fetchAll();
+} catch (PDOException $e) {
+ echo "Error: " . $e->getMessage();
+ $contacts = [];
+}
+?>
+
+
+ ' . $_SESSION['success_message'] . '
';
+ unset($_SESSION['success_message']);
+ }
+ if (isset($_SESSION['error_message'])) {
+ echo '' . $_SESSION['error_message'] . '
';
+ unset($_SESSION['error_message']);
+ }
+ ?>
+
+
Contacts
+
Add Contact
+
+
+
+
+
+
+
+
diff --git a/db/config.php b/db/config.php
index cc9229f..c48fbb2 100644
--- a/db/config.php
+++ b/db/config.php
@@ -15,3 +15,37 @@ function db() {
}
return $pdo;
}
+
+function db_init() {
+ $pdo = db();
+ $contacts_table_sql = ""
+ CREATE TABLE IF NOT EXISTS `contacts` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL,
+ `company` varchar(255) DEFAULT NULL,
+ `email` varchar(255) DEFAULT NULL,
+ `phone` varchar(255) DEFAULT NULL,
+ `source` varchar(255) DEFAULT NULL,
+ `tags` varchar(255) DEFAULT NULL,
+ `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+ """;
+ $pdo->exec($contacts_table_sql);
+
+ $deals_table_sql = ""
+ CREATE TABLE IF NOT EXISTS `deals` (
+ `id` INT AUTO_INCREMENT PRIMARY KEY,
+ `title` VARCHAR(255) NOT NULL,
+ `value` DECIMAL(10, 2) NOT NULL,
+ `stage` VARCHAR(50) NOT NULL,
+ `close_date` DATE,
+ `contact_id` INT NOT NULL,
+ `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY (contact_id) REFERENCES contacts(id) ON DELETE CASCADE
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+ """;
+ $pdo->exec($deals_table_sql);
+}
+
+db_init();
diff --git a/delete_contact.php b/delete_contact.php
new file mode 100644
index 0000000..15c6ac4
--- /dev/null
+++ b/delete_contact.php
@@ -0,0 +1,41 @@
+prepare("SELECT COUNT(*) FROM deals WHERE contact_id = :contact_id");
+ $stmt->bindParam(':contact_id', $contact_id, PDO::PARAM_INT);
+ $stmt->execute();
+ $deal_count = $stmt->fetchColumn();
+
+ if ($deal_count > 0) {
+ $_SESSION['error_message'] = "Cannot delete contact. It is associated with {$deal_count} deal(s). Please reassign or delete the deals first.";
+ } else {
+ // No associated deals, proceed with deletion
+ $stmt = $pdo->prepare("DELETE FROM contacts WHERE id = :id");
+ $stmt->bindParam(':id', $contact_id, PDO::PARAM_INT);
+
+ if ($stmt->execute() && $stmt->rowCount() > 0) {
+ $_SESSION['success_message'] = "Contact deleted successfully.";
+ } else {
+ $_SESSION['error_message'] = "Failed to delete contact or contact not found.";
+ }
+ }
+} catch (PDOException $e) {
+ $_SESSION['error_message'] = "Database error: " . $e->getMessage();
+}
+
+header("Location: contacts.php");
+exit;
+?>
\ No newline at end of file
diff --git a/delete_deal.php b/delete_deal.php
new file mode 100644
index 0000000..12c347d
--- /dev/null
+++ b/delete_deal.php
@@ -0,0 +1,28 @@
+prepare("DELETE FROM deals WHERE id = :id");
+ $stmt->bindParam(':id', $deal_id, PDO::PARAM_INT);
+
+ if ($stmt->execute() && $stmt->rowCount() > 0) {
+ $_SESSION['success_message'] = "Deal deleted successfully.";
+ } else {
+ $_SESSION['error_message'] = "Failed to delete deal or deal not found.";
+ }
+} catch (PDOException $e) {
+ $_SESSION['error_message'] = "Database error: " . $e->getMessage();
+}
+
+header("Location: index.php");
+exit;
+?>
\ No newline at end of file
diff --git a/edit_contact.php b/edit_contact.php
new file mode 100644
index 0000000..d51e9d5
--- /dev/null
+++ b/edit_contact.php
@@ -0,0 +1,99 @@
+prepare("UPDATE contacts SET name = :name, company = :company, email = :email, phone = :phone, source = :source, tags = :tags WHERE id = :id");
+ $stmt->execute([
+ ':name' => $name,
+ ':company' => $company,
+ ':email' => $email,
+ ':phone' => $phone,
+ ':source' => $source,
+ ':tags' => $tags,
+ ':id' => $id
+ ]);
+ header("Location: contacts.php?status=updated");
+ exit;
+ } catch (PDOException $e) {
+ $error = "Database error: " . $e->getMessage();
+ }
+ }
+}
+
+try {
+ $stmt = $pdo->prepare("SELECT * FROM contacts WHERE id = :id");
+ $stmt->execute([':id' => $id]);
+ $contact = $stmt->fetch();
+
+ if (!$contact) {
+ header("Location: contacts.php");
+ exit;
+ }
+} catch (PDOException $e) {
+ echo "Error: " . $e->getMessage();
+ exit;
+}
+?>
+
+
+
Edit Contact
+
+
+
+
+
+
+
+
+
diff --git a/edit_deal.php b/edit_deal.php
new file mode 100644
index 0000000..730e0ce
--- /dev/null
+++ b/edit_deal.php
@@ -0,0 +1,116 @@
+query("SELECT id, name, company FROM contacts ORDER BY name ASC");
+ $contacts = $stmt->fetchAll();
+} catch (PDOException $e) {
+ $error = "Error fetching contacts: " . $e->getMessage();
+ $contacts = [];
+}
+
+if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+ $title = $_POST['title'] ?? '';
+ $value = $_POST['value'] ?? 0;
+ $stage = $_POST['stage'] ?? 'Lead';
+ $contact_id = $_POST['contact_id'] ?? null;
+ $close_date = $_POST['close_date'] ?? null;
+
+ if (empty($title) || empty($contact_id)) {
+ $error = "Title and contact are required.";
+ } else {
+ try {
+ $stmt = $pdo->prepare("UPDATE deals SET title = :title, value = :value, stage = :stage, contact_id = :contact_id, close_date = :close_date WHERE id = :id");
+ $stmt->execute([
+ ':title' => $title,
+ ':value' => $value,
+ ':stage' => $stage,
+ ':contact_id' => $contact_id,
+ ':close_date' => !empty($close_date) ? $close_date : null,
+ ':id' => $id
+ ]);
+ header("Location: index.php?status=deal_updated");
+ exit;
+ } catch (PDOException $e) {
+ $error = "Database error: " . $e->getMessage();
+ }
+ }
+}
+
+try {
+ $stmt = $pdo->prepare("SELECT * FROM deals WHERE id = :id");
+ $stmt->execute([':id' => $id]);
+ $deal = $stmt->fetch();
+
+ if (!$deal) {
+ header("Location: index.php");
+ exit;
+ }
+} catch (PDOException $e) {
+ echo "Error: " . $e->getMessage();
+ exit;
+}
+
+$deal_stages = ['Lead', 'Prospecting', 'Qualification', 'Proposal', 'Negotiation', 'Closed Won', 'Closed Lost'];
+
+?>
+
+
+
Edit Deal
+
+
+
+
+
+
+
+
+
diff --git a/footer.php b/footer.php
new file mode 100644
index 0000000..88941e6
--- /dev/null
+++ b/footer.php
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+