Auto commit: 2025-10-26T16:53:16.288Z

This commit is contained in:
Flatlogic Bot 2025-10-26 16:53:16 +00:00
parent b8ab420fdd
commit 7fd4fb5808
10 changed files with 502 additions and 5 deletions

View File

@ -66,8 +66,8 @@ try {
</td>
<td><?php echo htmlspecialchars(date('M d, Y', strtotime($customer['created_at']))); ?></td>
<td>
<button class="btn btn-sm btn-outline-secondary"><i class="bi bi-pencil"></i></button>
<button class="btn btn-sm btn-outline-danger"><i class="bi bi-trash"></i></button>
<a href="edit_customer.php?id=<?php echo $customer['id']; ?>" class="btn btn-sm btn-outline-secondary"><i class="bi bi-pencil"></i></a>
<a href="delete_customer.php?id=<?php echo $customer['id']; ?>" class="btn btn-sm btn-outline-danger" onclick="return confirm('Are you sure you want to delete this customer?');"><i class="bi bi-trash"></i></a>
</td>
</tr>
<?php endforeach; ?>

19
delete_customer.php Normal file
View File

@ -0,0 +1,19 @@
<?php
require_once 'db/config.php';
$customer_id = $_GET['id'] ?? null;
if ($customer_id) {
try {
$pdo = db();
$stmt = $pdo->prepare('DELETE FROM customers WHERE id = ?');
$stmt->execute([$customer_id]);
} catch (PDOException $e) {
// Optional: Log the error or show a generic error message
// For simplicity, we redirect without an error message
}
}
header('Location: customers.php');
exit;
?>

19
delete_invoice.php Normal file
View File

@ -0,0 +1,19 @@
<?php
require_once 'db/config.php';
$invoice_id = $_GET['id'] ?? null;
if ($invoice_id) {
try {
$pdo = db();
$stmt = $pdo->prepare('DELETE FROM invoices WHERE id = ?');
$stmt->execute([$invoice_id]);
} catch (PDOException $e) {
// Optional: Log the error or show a generic error message
// For simplicity, we redirect without an error message
}
}
header('Location: invoices.php');
exit;
?>

19
delete_plan.php Normal file
View File

@ -0,0 +1,19 @@
<?php
require_once 'db/config.php';
$plan_id = $_GET['id'] ?? null;
if ($plan_id) {
try {
$pdo = db();
$stmt = $pdo->prepare('DELETE FROM plans WHERE id = ?');
$stmt->execute([$plan_id]);
} catch (PDOException $e) {
// Optional: Log the error or show a generic error message
// For simplicity, we redirect without an error message
}
}
header('Location: plans.php');
exit;
?>

89
edit_customer.php Normal file
View File

@ -0,0 +1,89 @@
<?php
require_once 'db/config.php';
$title = 'Edit Customer - Billing';
$page = 'customers';
require_once 'templates/header.php';
$customer_id = $_GET['id'] ?? null;
$error_message = '';
$success_message = '';
$customer = null;
if (!$customer_id) {
header('Location: customers.php');
exit;
}
try {
$pdo = db();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim($_POST['name']);
$email = trim($_POST['email']);
$status = trim($_POST['status']);
if (empty($name) || empty($email) || empty($status)) {
$error_message = 'Please fill in all required fields.';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$error_message = 'Invalid email format.';
} else {
$stmt = $pdo->prepare('UPDATE customers SET name = ?, email = ?, status = ? WHERE id = ?');
$stmt->execute([$name, $email, $status, $customer_id]);
$success_message = 'Customer updated successfully!';
}
}
$stmt = $pdo->prepare('SELECT id, name, email, status FROM customers WHERE id = ?');
$stmt->execute([$customer_id]);
$customer = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$customer) {
header('Location: customers.php');
exit;
}
} catch (PDOException $e) {
$error_message = 'Database error: ' . $e->getMessage();
}
?>
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Edit Customer</h1>
</div>
<?php if ($error_message): ?>
<div class="alert alert-danger"><?php echo htmlspecialchars($error_message); ?></div>
<?php endif; ?>
<?php if ($success_message): ?>
<div class="alert alert-success"><?php echo htmlspecialchars($success_message); ?></div>
<?php endif; ?>
<?php if ($customer): ?>
<form action="edit_customer.php?id=<?php echo htmlspecialchars($customer_id); ?>" method="POST">
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control" id="name" name="name" value="<?php echo htmlspecialchars($customer['name']); ?>" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="email" value="<?php echo htmlspecialchars($customer['email']); ?>" required>
</div>
<div class="mb-3">
<label for="status" class="form-label">Status</label>
<select class="form-select" id="status" name="status" required>
<option value="active" <?php echo ($customer['status'] === 'active') ? 'selected' : ''; ?>>Active</option>
<option value="inactive" <?php echo ($customer['status'] === 'inactive') ? 'selected' : ''; ?>>Inactive</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Save Changes</button>
<a href="customers.php" class="btn btn-secondary">Cancel</a>
</form>
<?php else: ?>
<p>Customer not found.</p>
<?php endif; ?>
<?php
require_once 'templates/footer.php';
?>

122
edit_invoice.php Normal file
View File

@ -0,0 +1,122 @@
<?php
require_once 'db/config.php';
$title = 'Edit Invoice - Billing';
$page = 'invoices';
require_once 'templates/header.php';
$invoice_id = $_GET['id'] ?? null;
$error_message = '';
$success_message = '';
$invoice = null;
if (!$invoice_id) {
header('Location: invoices.php');
exit;
}
try {
$pdo = db();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$customer_id = trim($_POST['customer_id']);
$plan_id = trim($_POST['plan_id']);
$amount = trim($_POST['amount']);
$status = trim($_POST['status']);
$due_date = trim($_POST['due_date']);
if (empty($customer_id) || empty($plan_id) || empty($amount) || empty($status) || empty($due_date)) {
$error_message = 'Please fill in all required fields.';
} elseif (!is_numeric($amount)) {
$error_message = 'Amount must be a number.';
} else {
$stmt = $pdo->prepare('UPDATE invoices SET customer_id = ?, plan_id = ?, amount = ?, status = ?, due_date = ? WHERE id = ?');
$stmt->execute([$customer_id, $plan_id, $amount, $status, $due_date, $invoice_id]);
$success_message = 'Invoice updated successfully!';
}
}
$stmt = $pdo->prepare('SELECT * FROM invoices WHERE id = ?');
$stmt->execute([$invoice_id]);
$invoice = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$invoice) {
header('Location: invoices.php');
exit;
}
$customers_stmt = $pdo->query('SELECT id, name FROM customers');
$customers = $customers_stmt->fetchAll(PDO::FETCH_ASSOC);
$plans_stmt = $pdo->query('SELECT id, name FROM plans');
$plans = $plans_stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
$error_message = 'Database error: ' . $e->getMessage();
}
?>
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Edit Invoice #<?php echo htmlspecialchars($invoice_id); ?></h1>
</div>
<?php if ($error_message): ?>
<div class="alert alert-danger"><?php echo htmlspecialchars($error_message); ?></div>
<?php endif; ?>
<?php if ($success_message): ?>
<div class="alert alert-success"><?php echo htmlspecialchars($success_message); ?></div>
<?php endif; ?>
<?php if ($invoice): ?>
<form action="edit_invoice.php?id=<?php echo htmlspecialchars($invoice_id); ?>" method="POST">
<div class="row">
<div class="col-md-6 mb-3">
<label for="customer_id" class="form-label">Customer</label>
<select class="form-select" id="customer_id" name="customer_id" required>
<?php foreach ($customers as $customer): ?>
<option value="<?php echo $customer['id']; ?>" <?php echo ($invoice['customer_id'] == $customer['id']) ? 'selected' : ''; ?>><?php echo htmlspecialchars($customer['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6 mb-3">
<label for="plan_id" class="form-label">Plan</label>
<select class="form-select" id="plan_id" name="plan_id" required>
<?php foreach ($plans as $plan): ?>
<option value="<?php echo $plan['id']; ?>" <?php echo ($invoice['plan_id'] == $plan['id']) ? 'selected' : ''; ?>><?php echo htmlspecialchars($plan['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="row">
<div class="col-md-4 mb-3">
<label for="amount" class="form-label">Amount</label>
<div class="input-group">
<span class="input-group-text">$</span>
<input type="number" step="0.01" class="form-control" id="amount" name="amount" value="<?php echo htmlspecialchars($invoice['amount']); ?>" required>
</div>
</div>
<div class="col-md-4 mb-3">
<label for="status" class="form-label">Status</label>
<select class="form-select" id="status" name="status" required>
<option value="Pending" <?php echo ($invoice['status'] === 'Pending') ? 'selected' : ''; ?>>Pending</option>
<option value="Paid" <?php echo ($invoice['status'] === 'Paid') ? 'selected' : ''; ?>>Paid</option>
<option value="Overdue" <?php echo ($invoice['status'] === 'Overdue') ? 'selected' : ''; ?>>Overdue</option>
</select>
</div>
<div class="col-md-4 mb-3">
<label for="due_date" class="form-label">Due Date</label>
<input type="date" class="form-control" id="due_date" name="due_date" value="<?php echo htmlspecialchars($invoice['due_date']); ?>" required>
</div>
</div>
<button type="submit" class="btn btn-primary">Save Changes</button>
<a href="invoices.php" class="btn btn-secondary">Cancel</a>
</form>
<?php else: ?>
<p>Invoice not found.</p>
<?php endif; ?>
<?php
require_once 'templates/footer.php';
?>

100
edit_plan.php Normal file
View File

@ -0,0 +1,100 @@
<?php
require_once 'db/config.php';
$title = 'Edit Plan - Billing';
$page = 'plans';
require_once 'templates/header.php';
$plan_id = $_GET['id'] ?? null;
$error_message = '';
$success_message = '';
$plan = null;
if (!$plan_id) {
header('Location: plans.php');
exit;
}
try {
$pdo = db();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim($_POST['name']);
$price = trim($_POST['price']);
$billing_cycle = trim($_POST['billing_cycle']);
$features = trim($_POST['features']);
if (empty($name) || empty($price) || empty($billing_cycle)) {
$error_message = 'Please fill in all required fields.';
} elseif (!is_numeric($price)) {
$error_message = 'Price must be a number.';
} else {
$features_json = json_encode(array_map('trim', explode("\n", $features)));
$stmt = $pdo->prepare('UPDATE plans SET name = ?, price = ?, billing_cycle = ?, features = ? WHERE id = ?');
$stmt->execute([$name, $price, $billing_cycle, $features_json, $plan_id]);
$success_message = 'Plan updated successfully!';
}
}
$stmt = $pdo->prepare('SELECT * FROM plans WHERE id = ?');
$stmt->execute([$plan_id]);
$plan = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$plan) {
header('Location: plans.php');
exit;
}
} catch (PDOException $e) {
$error_message = 'Database error: ' . $e->getMessage();
}
?>
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Edit Plan</h1>
</div>
<?php if ($error_message): ?>
<div class="alert alert-danger"><?php echo htmlspecialchars($error_message); ?></div>
<?php endif; ?>
<?php if ($success_message): ?>
<div class="alert alert-success"><?php echo htmlspecialchars($success_message); ?></div>
<?php endif; ?>
<?php if ($plan): ?>
<form action="edit_plan.php?id=<?php echo htmlspecialchars($plan_id); ?>" method="POST">
<div class="mb-3">
<label for="name" class="form-label">Plan Name</label>
<input type="text" class="form-control" id="name" name="name" value="<?php echo htmlspecialchars($plan['name']); ?>" required>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="price" class="form-label">Price</label>
<div class="input-group">
<span class="input-group-text">$</span>
<input type="number" step="0.01" class="form-control" id="price" name="price" value="<?php echo htmlspecialchars($plan['price']); ?>" required>
</div>
</div>
<div class="col-md-6 mb-3">
<label for="billing_cycle" class="form-label">Billing Cycle</label>
<select class="form-select" id="billing_cycle" name="billing_cycle" required>
<option value="monthly" <?php echo ($plan['billing_cycle'] === 'monthly') ? 'selected' : ''; ?>>Monthly</option>
<option value="yearly" <?php echo ($plan['billing_cycle'] === 'yearly') ? 'selected' : ''; ?>>Yearly</option>
</select>
</div>
</div>
<div class="mb-3">
<label for="features" class="form-label">Features (one per line)</label>
<textarea class="form-control" id="features" name="features" rows="5" required><?php echo htmlspecialchars(implode("\n", json_decode($plan['features'], true))); ?></textarea>
</div>
<button type="submit" class="btn btn-primary">Save Changes</button>
<a href="plans.php" class="btn btn-secondary">Cancel</a>
</form>
<?php else: ?>
<p>Plan not found.</p>
<?php endif; ?>
<?php
require_once 'templates/footer.php';
?>

View File

@ -65,8 +65,9 @@ $status_colors = [
<td><?php echo date('M d, Y', strtotime($invoice['due_date'])); ?></td>
<td><?php echo date('M d, Y', strtotime($invoice['created_at'])); ?></td>
<td>
<button class="btn btn-sm btn-outline-secondary"><i class="bi bi-eye"></i></button>
<button class="btn btn-sm btn-outline-secondary"><i class="bi bi-pencil"></i></button>
<a href="view_invoice.php?id=<?php echo $invoice['id']; ?>" class="btn btn-sm btn-outline-secondary"><i class="bi bi-eye"></i></a>
<a href="edit_invoice.php?id=<?php echo $invoice['id']; ?>" class="btn btn-sm btn-outline-secondary"><i class="bi bi-pencil"></i></a>
<a href="delete_invoice.php?id=<?php echo $invoice['id']; ?>" class="btn btn-sm btn-outline-danger" onclick="return confirm('Are you sure you want to delete this invoice?');"><i class="bi bi-trash"></i></a>
</td>
</tr>
<?php endforeach; ?>

View File

@ -45,7 +45,12 @@ $plans = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
?>
</ul>
<button type="button" class="w-100 btn btn-lg btn-outline-primary">Sign up</button>
<div class="mt-auto">
<div class="d-flex justify-content-center gap-2">
<a href="edit_plan.php?id=<?php echo $plan['id']; ?>" class="btn btn-sm btn-outline-secondary w-100"><i class="bi bi-pencil"></i> Edit</a>
<a href="delete_plan.php?id=<?php echo $plan['id']; ?>" class="btn btn-sm btn-outline-danger w-100" onclick="return confirm('Are you sure you want to delete this plan?');"><i class="bi bi-trash"></i> Delete</a>
</div>
</div>
</div>
</div>
</div>

123
view_invoice.php Normal file
View File

@ -0,0 +1,123 @@
<?php
require_once 'db/config.php';
$title = 'View Invoice - Billing';
$page = 'invoices';
require_once 'templates/header.php';
$invoice_id = $_GET['id'] ?? null;
$invoice = null;
if (!$invoice_id) {
header('Location: invoices.php');
exit;
}
try {
$pdo = db();
$stmt = $pdo->prepare('
SELECT
i.*,
c.name AS customer_name, c.email AS customer_email,
p.name AS plan_name
FROM invoices i
JOIN customers c ON i.customer_id = c.id
JOIN plans p ON i.plan_id = p.id
WHERE i.id = ?
');
$stmt->execute([$invoice_id]);
$invoice = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$invoice) {
header('Location: invoices.php');
exit;
}
} catch (PDOException $e) {
$error_message = 'Database error: ' . $e->getMessage();
}
$status_colors = [
'Paid' => 'success',
'Pending' => 'warning',
'Overdue' => 'danger',
];
?>
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Invoice #<?php echo htmlspecialchars($invoice['id']); ?></h1>
<div class="btn-toolbar mb-2 mb-md-0">
<a href="edit_invoice.php?id=<?php echo $invoice['id']; ?>" class="btn btn-sm btn-outline-secondary me-2">
<i class="bi bi-pencil"></i> Edit
</a>
<button class="btn btn-sm btn-outline-primary" onclick="window.print();">
<i class="bi bi-printer"></i> Print
</button>
</div>
</div>
<?php if (isset($error_message)): ?>
<div class="alert alert-danger"><?php echo htmlspecialchars($error_message); ?></div>
<?php else: ?>
<div class="card">
<div class="card-header">
<div class="row align-items-center">
<div class="col-6">
<h5 class="mb-0">Invoice Details</h5>
</div>
<div class="col-6 text-end">
Status:
<span class="badge bg-<?php echo $status_colors[$invoice['status']] ?? 'secondary'; ?>">
<?php echo htmlspecialchars($invoice['status']); ?>
</span>
</div>
</div>
</div>
<div class="card-body">
<div class="row mb-4">
<div class="col-md-6">
<h6>Billed To:</h6>
<p class="mb-1"><?php echo htmlspecialchars($invoice['customer_name']); ?></p>
<p class="mb-0"><?php echo htmlspecialchars($invoice['customer_email']); ?></p>
</div>
<div class="col-md-6 text-md-end mt-3 mt-md-0">
<h6>Invoice Info:</h6>
<p class="mb-1"><strong>Invoice #:</strong> <?php echo htmlspecialchars($invoice['id']); ?></p>
<p class="mb-1"><strong>Created Date:</strong> <?php echo date('M d, Y', strtotime($invoice['created_at'])); ?></p>
<p class="mb-0"><strong>Due Date:</strong> <?php echo date('M d, Y', strtotime($invoice['due_date'])); ?></p>
</div>
</div>
<div class="table-responsive">
<table class="table table-bordered">
<thead class="table-light">
<tr>
<th scope="col">Description</th>
<th scope="col" class="text-end">Amount</th>
</tr>
</thead>
<tbody>
<tr>
<td>Subscription: <?php echo htmlspecialchars($invoice['plan_name']); ?></td>
<td class="text-end">$<?php echo number_format($invoice['amount'], 2); ?></td>
</tr>
</tbody>
<tfoot class="table-light">
<tr>
<th scope="row" class="text-end">Total:</th>
<th class="text-end">$<?php echo number_format($invoice['amount'], 2); ?></th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
<div class="text-center mt-4">
<a href="invoices.php" class="btn btn-secondary">Back to Invoices</a>
</div>
<?php endif; ?>
<?php
require_once 'templates/footer.php';
?>