Compare commits

..

No commits in common. "ai-dev" and "master" have entirely different histories.

25 changed files with 146 additions and 1171 deletions

View File

@ -1,84 +0,0 @@
<?php
require_once 'auth.php';
$pageTitle = "Add Task";
include 'partials/header.php';
require_once __DIR__ . '/../db/config.php';
$title = $icon = $description = $status = '';
$errors = [];
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$title = trim($_POST['title']);
$icon = trim($_POST['icon']);
$description = trim($_POST['description']);
$status = trim($_POST['status']);
if (empty($title)) {
$errors['title'] = 'Title is required';
}
if (empty($icon)) {
$errors['icon'] = 'Icon is required';
}
if (empty($errors)) {
try {
$pdo = db();
$sql = "INSERT INTO tasks (title, icon, description, status) VALUES (?, ?, ?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute([$title, $icon, $description, $status]);
// Redirect to tasks list
header("Location: tasks.php");
exit;
} catch (PDOException $e) {
// Ideally, log this error
$errors['db'] = "Database error: " . $e->getMessage();
}
}
}
?>
<div class="container-fluid">
<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">Add New Task</h1>
</div>
<?php if (!empty($errors['db'])): ?>
<div class="alert alert-danger"><?php echo htmlspecialchars($errors['db']); ?></div>
<?php endif; ?>
<form method="POST" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
<div class="mb-3">
<label for="title" class="form-label">Title</label>
<input type="text" class="form-control <?php echo !empty($errors['title']) ? 'is-invalid' : ''; ?>" id="title" name="title" value="<?php echo htmlspecialchars($title); ?>">
<?php if (!empty($errors['title'])): ?>
<div class="invalid-feedback"><?php echo $errors['title']; ?></div>
<?php endif; ?>
</div>
<div class="mb-3">
<label for="icon" class="form-label">Icon</label>
<input type="text" class="form-control <?php echo !empty($errors['icon']) ? 'is-invalid' : ''; ?>" id="icon" name="icon" value="<?php echo htmlspecialchars($icon); ?>">
<?php if (!empty($errors['icon'])): ?>
<div class="invalid-feedback"><?php echo $errors['icon']; ?></div>
<?php endif; ?>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control" id="description" name="description" rows="3"><?php echo htmlspecialchars($description); ?></textarea>
</div>
<div class="mb-3">
<label for="status" class="form-label">Status</label>
<select class="form-control" id="status" name="status">
<option value="pending" selected>Pending</option>
<option value="in_progress">In Progress</option>
<option value="completed">Completed</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Save Task</button>
<a href="tasks.php" class="btn btn-secondary">Cancel</a>
</form>
</div>
<?php include 'partials/footer.php'; ?>

View File

@ -1,104 +0,0 @@
<?php
require_once 'auth.php';
$pageTitle = "Add User";
include 'partials/header.php';
require_once __DIR__ . '/../db/config.php';
$name = $email = $password = $password_confirm = '';
$errors = [];
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$name = trim($_POST['name']);
$email = trim($_POST['email']);
$password = $_POST['password'];
$password_confirm = $_POST['password_confirm'];
if (empty($name)) {
$errors['name'] = 'Name is required';
}
if (empty($email)) {
$errors['email'] = 'Email is required';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors['email'] = 'Invalid email format';
}
if (empty($password)) {
$errors['password'] = 'Password is required';
}
if ($password !== $password_confirm) {
$errors['password_confirm'] = 'Passwords do not match';
}
if (empty($errors)) {
try {
$pdo = db();
// Check if email already exists
$stmt = $pdo->prepare("SELECT id FROM users WHERE email = ?");
$stmt->execute([$email]);
if ($stmt->fetch()) {
$errors['email'] = 'Email already exists';
} else {
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
$sql = "INSERT INTO users (name, email, password, role) VALUES (?, ?, ?, 'user')";
$stmt = $pdo->prepare($sql);
$stmt->execute([$name, $email, $hashed_password]);
// Redirect to users list
header("Location: users.php");
exit;
}
} catch (PDOException $e) {
// Ideally, log this error
$errors['db'] = "Database error: " . $e->getMessage();
}
}
}
?>
<div class="container-fluid">
<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">Add New User</h1>
</div>
<?php if (!empty($errors['db'])): ?>
<div class="alert alert-danger"><?php echo htmlspecialchars($errors['db']); ?></div>
<?php endif; ?>
<form method="POST" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control <?php echo !empty($errors['name']) ? 'is-invalid' : ''; ?>" id="name" name="name" value="<?php echo htmlspecialchars($name); ?>">
<?php if (!empty($errors['name'])): ?>
<div class="invalid-feedback"><?php echo $errors['name']; ?></div>
<?php endif; ?>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email address</label>
<input type="email" class="form-control <?php echo !empty($errors['email']) ? 'is-invalid' : ''; ?>" id="email" name="email" value="<?php echo htmlspecialchars($email); ?>">
<?php if (!empty($errors['email'])): ?>
<div class="invalid-feedback"><?php echo $errors['email']; ?></div>
<?php endif; ?>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control <?php echo !empty($errors['password']) ? 'is-invalid' : ''; ?>" id="password" name="password">
<?php if (!empty($errors['password'])): ?>
<div class="invalid-feedback"><?php echo $errors['password']; ?></div>
<?php endif; ?>
</div>
<div class="mb-3">
<label for="password_confirm" class="form-label">Confirm Password</label>
<input type="password" class="form-control <?php echo !empty($errors['password_confirm']) ? 'is-invalid' : ''; ?>" id="password_confirm" name="password_confirm">
<?php if (!empty($errors['password_confirm'])): ?>
<div class="invalid-feedback"><?php echo $errors['password_confirm']; ?></div>
<?php endif; ?>
</div>
<button type="submit" class="btn btn-primary">Save User</button>
<a href="users.php" class="btn btn-secondary">Cancel</a>
</form>
</div>
<?php include 'partials/footer.php'; ?>

View File

@ -1,85 +0,0 @@
body {
font-size: .875rem;
}
.feather {
width: 16px;
height: 16px;
vertical-align: text-bottom;
}
/*
* Sidebar
*/
.sidebar {
position: fixed;
top: 0;
bottom: 0;
left: 0;
z-index: 100; /* Behind the navbar */
padding: 48px 0 0; /* Height of navbar */
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
}
.sidebar-sticky {
position: relative;
top: 0;
height: calc(100vh - 48px);
padding-top: .5rem;
overflow-x: hidden;
overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
}
.sidebar .nav-link {
font-weight: 500;
color: #333;
}
.sidebar .nav-link .feather {
margin-right: 4px;
color: #727272;
}
.sidebar .nav-link.active {
color: #2470dc;
}
.sidebar .nav-link:hover .feather,
.sidebar .nav-link.active .feather {
color: inherit;
}
.sidebar-heading {
font-size: .75rem;
text-transform: uppercase;
}
/*
* Navbar
*/
.navbar-brand {
padding-top: .75rem;
padding-bottom: .75rem;
font-size: 1rem;
background-color: rgba(0, 0, 0, .25);
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .25);
}
.navbar .form-control {
padding: .75rem 1rem;
border-width: 0;
border-radius: 0;
}
.form-control-dark {
color: #fff;
background-color: rgba(255, 255, 255, .1);
border-color: rgba(255, 255, 255, .1);
}
.form-control-dark:focus {
border-color: transparent;
box-shadow: 0 0 0 3px rgba(255, 255, 255, .25);
}

View File

@ -1,12 +0,0 @@
<?php
session_start();
if (!isset($_SESSION['user_id'])) {
header("Location: ../login.php");
exit;
}
// Optional: Role-based access control
function is_admin() {
return isset($_SESSION['user_role']) && $_SESSION['user_role'] === 'admin';
}

View File

@ -1,25 +0,0 @@
<?php
require_once 'auth.php';
require_once __DIR__ . '/../db/config.php';
// Check if ID is set
if (!isset($_GET['id']) || empty($_GET['id'])) {
header("Location: tasks.php");
exit;
}
$id = $_GET['id'];
try {
$pdo = db();
$sql = "DELETE FROM tasks WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$id]);
// Redirect back to task list
header("Location: tasks.php");
exit;
} catch (PDOException $e) {
// For a real app, you'd log this error and show a user-friendly message.
die("Error: Could not delete task. " . $e->getMessage());
}

View File

@ -1,25 +0,0 @@
<?php
require_once 'auth.php';
require_once __DIR__ . '/../db/config.php';
// Check if ID is set
if (!isset($_GET['id']) || empty($_GET['id'])) {
header("Location: users.php");
exit;
}
$id = $_GET['id'];
try {
$pdo = db();
$sql = "DELETE FROM users WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$id]);
// Redirect back to user list
header("Location: users.php");
exit;
} catch (PDOException $e) {
// For a real app, you'd log this error and show a user-friendly message.
die("Error: Could not delete user. " . $e->getMessage());
}

View File

@ -1,104 +0,0 @@
<?php
require_once 'auth.php';
$pageTitle = "Edit Task";
include 'partials/header.php';
require_once __DIR__ . '/../db/config.php';
$id = $_GET['id'] ?? null;
if (!$id) {
header("Location: tasks.php");
exit;
}
$pdo = db();
$title = $icon = $description = $status = '';
$errors = [];
// Fetch task data for the form
$stmt = $pdo->prepare("SELECT * FROM tasks WHERE id = ?");
$stmt->execute([$id]);
$task = $stmt->fetch();
if (!$task) {
// Optional: Add a flash message here
header("Location: tasks.php");
exit;
}
$title = $task['title'];
$icon = $task['icon'];
$description = $task['description'];
$status = $task['status'];
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$title = trim($_POST['title']);
$icon = trim($_POST['icon']);
$description = trim($_POST['description']);
$status = trim($_POST['status']);
if (empty($title)) {
$errors['title'] = 'Title is required';
}
if (empty($icon)) {
$errors['icon'] = 'Icon is required';
}
if (empty($errors)) {
try {
$sql = "UPDATE tasks SET title = ?, icon = ?, description = ?, status = ? WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$title, $icon, $description, $status, $id]);
header("Location: tasks.php");
exit;
} catch (PDOException $e) {
$errors['db'] = "Database error: " . $e->getMessage();
}
}
}
?>
<div class="container-fluid">
<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 Task</h1>
</div>
<?php if (!empty($errors['db'])): ?>
<div class="alert alert-danger"><?php echo htmlspecialchars($errors['db']); ?></div>
<?php endif; ?>
<form method="POST" action="edit-task.php?id=<?php echo htmlspecialchars($id); ?>">
<div class="mb-3">
<label for="title" class="form-label">Title</label>
<input type="text" class="form-control <?php echo !empty($errors['title']) ? 'is-invalid' : ''; ?>" id="title" name="title" value="<?php echo htmlspecialchars($title); ?>">
<?php if (!empty($errors['title'])): ?>
<div class="invalid-feedback"><?php echo $errors['title']; ?></div>
<?php endif; ?>
</div>
<div class="mb-3">
<label for="icon" class="form-label">Icon</label>
<input type="text" class="form-control <?php echo !empty($errors['icon']) ? 'is-invalid' : ''; ?>" id="icon" name="icon" value="<?php echo htmlspecialchars($icon); ?>">
<?php if (!empty($errors['icon'])): ?>
<div class="invalid-feedback"><?php echo $errors['icon']; ?></div>
<?php endif; ?>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control" id="description" name="description" rows="3"><?php echo htmlspecialchars($description); ?></textarea>
</div>
<div class="mb-3">
<label for="status" class="form-label">Status</label>
<select class="form-control" id="status" name="status">
<option value="pending" <?php echo ($status == 'pending') ? 'selected' : ''; ?>>Pending</option>
<option value="in_progress" <?php echo ($status == 'in_progress') ? 'selected' : ''; ?>>In Progress</option>
<option value="completed" <?php echo ($status == 'completed') ? 'selected' : ''; ?>>Completed</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Update Task</button>
<a href="tasks.php" class="btn btn-secondary">Cancel</a>
</form>
</div>
<?php include 'partials/footer.php'; ?>

View File

@ -1,124 +0,0 @@
<?php
require_once 'auth.php';
$pageTitle = "Edit User";
include 'partials/header.php';
require_once __DIR__ . '/../db/config.php';
$id = $_GET['id'] ?? null;
if (!$id) {
header("Location: users.php");
exit;
}
$pdo = db();
$name = $email = '';
$errors = [];
// Fetch user data for the form
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$id]);
$user = $stmt->fetch();
if (!$user) {
// Optional: Add a flash message here
header("Location: users.php");
exit;
}
$name = $user['name'];
$email = $user['email'];
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$name = trim($_POST['name']);
$email = trim($_POST['email']);
$password = $_POST['password'];
$password_confirm = $_POST['password_confirm'];
if (empty($name)) {
$errors['name'] = 'Name is required';
}
if (empty($email)) {
$errors['email'] = 'Email is required';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors['email'] = 'Invalid email format';
}
if (!empty($password) && ($password !== $password_confirm)) {
$errors['password_confirm'] = 'Passwords do not match';
}
if (empty($errors)) {
try {
// Check if email already exists for another user
$stmt = $pdo->prepare("SELECT id FROM users WHERE email = ? AND id != ?");
$stmt->execute([$email, $id]);
if ($stmt->fetch()) {
$errors['email'] = 'Email already exists for another user';
} else {
if (!empty($password)) {
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
$sql = "UPDATE users SET name = ?, email = ?, password = ? WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$name, $email, $hashed_password, $id]);
} else {
$sql = "UPDATE users SET name = ?, email = ? WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$name, $email, $id]);
}
header("Location: users.php");
exit;
}
} catch (PDOException $e) {
$errors['db'] = "Database error: " . $e->getMessage();
}
}
}
?>
<div class="container-fluid">
<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 User</h1>
</div>
<?php if (!empty($errors['db'])): ?>
<div class="alert alert-danger"><?php echo htmlspecialchars($errors['db']); ?></div>
<?php endif; ?>
<form method="POST" action="edit-user.php?id=<?php echo htmlspecialchars($id); ?>">
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control <?php echo !empty($errors['name']) ? 'is-invalid' : ''; ?>" id="name" name="name" value="<?php echo htmlspecialchars($name); ?>">
<?php if (!empty($errors['name'])): ?>
<div class="invalid-feedback"><?php echo $errors['name']; ?></div>
<?php endif; ?>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email address</label>
<input type="email" class="form-control <?php echo !empty($errors['email']) ? 'is-invalid' : ''; ?>" id="email" name="email" value="<?php echo htmlspecialchars($email); ?>">
<?php if (!empty($errors['email'])): ?>
<div class="invalid-feedback"><?php echo $errors['email']; ?></div>
<?php endif; ?>
</div>
<div class="mb-3">
<label for="password" class="form-label">New Password (leave blank to keep current password)</label>
<input type="password" class="form-control <?php echo !empty($errors['password']) ? 'is-invalid' : ''; ?>" id="password" name="password">
<?php if (!empty($errors['password'])): ?>
<div class="invalid-feedback"><?php echo $errors['password']; ?></div>
<?php endif; ?>
</div>
<div class="mb-3">
<label for="password_confirm" class="form-label">Confirm New Password</label>
<input type="password" class="form-control <?php echo !empty($errors['password_confirm']) ? 'is-invalid' : ''; ?>" id="password_confirm" name="password_confirm">
<?php if (!empty($errors['password_confirm'])): ?>
<div class="invalid-feedback"><?php echo $errors['password_confirm']; ?></div>
<?php endif; ?>
</div>
<button type="submit" class="btn btn-primary">Update User</button>
<a href="users.php" class="btn btn-secondary">Cancel</a>
</form>
</div>
<?php include 'partials/footer.php'; ?>

View File

@ -1,4 +0,0 @@
<?php
header("Location: users.php");
exit();
?>

View File

@ -1,6 +0,0 @@
<?php
session_start();
session_unset();
session_destroy();
header("Location: ../login.php");
exit;

View File

@ -1,12 +0,0 @@
</main>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script>
feather.replace()
</script>
</body>
</html>

View File

@ -1,54 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?php echo isset($pageTitle) ? htmlspecialchars($pageTitle) : "Admin"; ?> - OldHelp</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="assets/css/style.css" rel="stylesheet">
</head>
<body>
<header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
<a class="navbar-brand col-md-3 col-lg-2 me-0 px-3" href="#">OldHelp Admin</a>
<button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-nav">
<div class="nav-item text-nowrap">
<a class="nav-link px-3" href="logout.php">Sign out</a>
</div>
</div>
</header>
<div class="container-fluid">
<div class="row">
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
<div class="position-sticky pt-3">
<?php
$currentPage = basename($_SERVER['PHP_SELF']);
?>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link <?php echo ($currentPage == 'users.php' || $currentPage == 'add-user.php' || $currentPage == 'edit-user.php') ? 'active' : ''; ?>" href="users.php">
<span data-feather="users"></span>
Users
</a>
</li>
<li class="nav-item">
<a class="nav-link <?php echo ($currentPage == 'tasks.php' || $currentPage == 'add-task.php' || $currentPage == 'edit-task.php') ? 'active' : ''; ?>" href="tasks.php">
<span data-feather="file-text"></span>
Tasks
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="../index.php">
<span data-feather="arrow-left"></span>
Back to Main Site
</a>
</li>
</ul>
</div>
</nav>
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">

View File

@ -1,105 +0,0 @@
<?php
require_once 'auth.php';
$pageTitle = "Task Management";
include 'partials/header.php';
require_once __DIR__ . '/../db/config.php';
$pdo = db();
// Search and filter logic
$search = $_GET['search'] ?? '';
$status = $_GET['status'] ?? '';
$sql = 'SELECT id, title, icon, description, status FROM tasks';
$params = [];
$whereClauses = [];
if ($search) {
$whereClauses[] = '(title LIKE ? OR description LIKE ?)';
$params[] = '%' . $search . '%';
$params[] = '%' . $search . '%';
}
if ($status) {
$whereClauses[] = 'status = ?';
$params[] = $status;
}
if (!empty($whereClauses)) {
$sql .= ' WHERE ' . implode(' AND ', $whereClauses);
}
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$tasks = $stmt->fetchAll();
?>
<div class="container-fluid">
<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">Task Management</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<a href="add-task.php" class="btn btn-sm btn-outline-secondary">
<span data-feather="plus-circle"></span>
Add Task
</a>
</div>
</div>
<!-- Search and filter form -->
<form method="GET" action="tasks.php" class="mb-3">
<div class="row g-2">
<div class="col-md-6">
<input type="text" name="search" class="form-control" placeholder="Search by title or description..." value="<?php echo htmlspecialchars($search); ?>">
</div>
<div class="col-md-4">
<select name="status" class="form-select">
<option value="">All Statuses</option>
<option value="pending" <?php echo ($status == 'pending') ? 'selected' : ''; ?>>Pending</option>
<option value="in_progress" <?php echo ($status == 'in_progress') ? 'selected' : ''; ?>>In Progress</option>
<option value="completed" <?php echo ($status == 'completed') ? 'selected' : ''; ?>>Completed</option>
</select>
</div>
<div class="col-md-2">
<button class="btn btn-primary w-100" type="submit">Filter</button>
</div>
</div>
</form>
<div class="table-responsive">
<table class="table table-striped table-sm">
<thead>
<tr>
<th>#</th>
<th>Title</th>
<th>Icon</th>
<th>Description</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($tasks)): ?>
<tr>
<td colspan="6" class="text-center">No tasks found.</td>
</tr>
<?php else: ?>
<?php foreach ($tasks as $task): ?>
<tr>
<td><?php echo htmlspecialchars($task['id']); ?></td>
<td><?php echo htmlspecialchars($task['title']); ?></td>
<td><i data-feather="<?php echo htmlspecialchars($task['icon']); ?>"></i></td>
<td><?php echo htmlspecialchars($task['description']); ?></td>
<td><?php echo htmlspecialchars($task['status']); ?></td>
<td>
<a href="edit-task.php?id=<?php echo $task['id']; ?>" class="btn btn-sm btn-outline-secondary">Edit</a>
<a href="delete-task.php?id=<?php echo $task['id']; ?>" class="btn btn-sm btn-outline-danger" onclick="return confirm('Are you sure you want to delete this task?');">Delete</a>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<?php include 'partials/footer.php'; ?>

View File

@ -1,74 +0,0 @@
<?php
require_once 'auth.php';
$pageTitle = "User Management";
include 'partials/header.php';
require_once __DIR__ . '/../db/config.php';
$pdo = db();
// Search logic
$search = $_GET['search'] ?? '';
if ($search) {
$stmt = $pdo->prepare('SELECT id, name, email, role FROM users WHERE name LIKE ? OR email LIKE ?');
$stmt->execute(['%' . $search . '%', '%' . $search . '%']);
} else {
$stmt = $pdo->query('SELECT id, name, email, role FROM users');
}
$users = $stmt->fetchAll();
?>
<div class="container-fluid">
<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">User Management</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<a href="add-user.php" class="btn btn-sm btn-outline-secondary">
<span data-feather="plus-circle"></span>
Add User
</a>
</div>
</div>
<!-- Search form -->
<form method="GET" action="users.php" class="mb-3">
<div class="input-group">
<input type="text" name="search" class="form-control" placeholder="Search by name or email..." value="<?php echo htmlspecialchars($search); ?>">
<button class="btn btn-outline-secondary" type="submit">Search</button>
</div>
</form>
<div class="table-responsive">
<table class="table table-striped table-sm">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Email</th>
<th>Role</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($users)): ?>
<tr>
<td colspan="5" class="text-center">No users found.</td>
</tr>
<?php else: ?>
<?php foreach ($users as $user): ?>
<tr>
<td><?php echo htmlspecialchars($user['id']); ?></td>
<td><?php echo htmlspecialchars($user['name']); ?></td>
<td><?php echo htmlspecialchars($user['email']); ?></td>
<td><?php echo htmlspecialchars($user['role']); ?></td>
<td>
<a href="edit-user.php?id=<?php echo $user['id']; ?>" class="btn btn-sm btn-outline-secondary">Edit</a>
<a href="delete-user.php?id=<?php echo $user['id']; ?>" class="btn btn-sm btn-outline-danger" onclick="return confirm('Are you sure you want to delete this user?');">Delete</a>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<?php include 'partials/footer.php'; ?>

View File

@ -1,87 +0,0 @@
body {
background-color: #F9FAFB;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
color: #374151;
}
.hero {
background: linear-gradient(135deg, #FFFFFF, #F9FAFB);
padding: 4rem 2rem;
border-bottom: 1px solid #E5E7EB;
text-align: center;
}
.hero h1 {
font-size: 3rem;
font-weight: 700;
color: #111827;
}
.hero p {
font-size: 1.25rem;
color: #6B7280;
}
.action-card {
border: 1px solid #E5E7EB;
border-radius: 0.75rem;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.05), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
cursor: pointer;
background-color: #ffffff;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.action-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
.action-card .icon {
width: 3rem;
height: 3rem;
stroke-width: 1.5;
color: #3B82F6;
margin: 1.5rem auto;
}
.action-card .card-body {
padding: 1.5rem;
text-align: center;
}
.action-card .card-title {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 0.5rem;
color: #111827;
}
.action-card .card-text {
color: #6B7280;
margin-bottom: 1.5rem;
}
.btn-primary {
background-color: #3B82F6;
border-color: #3B82F6;
font-weight: 600;
padding: 0.75rem 1.5rem;
border-radius: 0.5rem;
transition: background-color 0.2s;
}
.btn-primary:hover {
background-color: #2563EB;
border-color: #2563EB;
}
.toast-container {
position: fixed;
top: 20px;
right: 20px;
z-index: 1055;
}

View File

@ -1,39 +0,0 @@
document.addEventListener('DOMContentLoaded', function () {
const actionCards = document.querySelectorAll('.action-card');
const toastContainer = document.querySelector('.toast-container');
const showToast = (message) => {
const toastEl = document.createElement('div');
toastEl.className = 'toast show';
toastEl.setAttribute('role', 'alert');
toastEl.setAttribute('aria-live', 'assertive');
toastEl.setAttribute('aria-atomic', 'true');
toastEl.innerHTML = `
<div class="toast-header">
<strong class="me-auto">OldHelp Assistant</strong>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
${message}
</div>
`;
toastContainer.appendChild(toastEl);
const toast = new bootstrap.Toast(toastEl, { delay: 5000 });
toast.show();
toastEl.addEventListener('hidden.bs.toast', () => {
toastEl.remove();
});
};
actionCards.forEach(card => {
card.addEventListener('click', () => {
const task = card.getAttribute('data-task');
showToast(`Help for <strong>${task}</strong> is on the way!`);
});
});
});

View File

@ -1,41 +0,0 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
// 1. Create migrations table if it doesn't exist
$pdo->exec("CREATE TABLE IF NOT EXISTS migrations (
id INT AUTO_INCREMENT PRIMARY KEY,
migration VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=INNODB;");
// 2. Get all migrations that have been run
$stmt = $pdo->query("SELECT migration FROM migrations");
$run_migrations = $stmt->fetchAll(PDO::FETCH_COLUMN);
// 3. Get all migration files
$migration_files = glob(__DIR__ . '/migrations/*.sql');
sort($migration_files);
// 4. Run new migrations
foreach ($migration_files as $file) {
$migration_name = basename($file);
if (!in_array($migration_name, $run_migrations)) {
$sql = file_get_contents($file);
$pdo->exec($sql);
// Record the migration
$stmt = $pdo->prepare("INSERT INTO migrations (migration) VALUES (?)");
$stmt->execute([$migration_name]);
echo "Migration successful: $migration_name\n";
}
}
echo "All migrations are up to date.\n";
} catch (PDOException $e) {
die("Migration failed: " . $e->getMessage() . "\n");
}

View File

@ -1,13 +0,0 @@
CREATE TABLE IF NOT EXISTS `users` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(255) NOT NULL,
`email` VARCHAR(255) NOT NULL UNIQUE,
`role` VARCHAR(50) NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Insert some dummy data
INSERT INTO `users` (`name`, `email`, `role`) VALUES
('John Doe', 'john.doe@example.com', 'admin'),
('Jane Smith', 'jane.smith@example.com', 'caregiver'),
('Peter Jones', 'peter.jones@example.com', 'elderly');

View File

@ -1,14 +0,0 @@
CREATE TABLE IF NOT EXISTS tasks (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
icon VARCHAR(100) NOT NULL,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=INNODB;
-- Insert some default tasks
INSERT INTO tasks (title, icon, description) VALUES
('Email', 'envelope', 'Get help with sending or reading emails.'),
('Internet', 'search', 'Get help with browsing the web.'),
('Video Call', 'video', 'Get help with making video calls to family and friends.'),
('Support', 'help-circle', 'Request technical support.');

View File

@ -1 +0,0 @@
ALTER TABLE users ADD COLUMN password VARCHAR(255) NOT NULL;

View File

@ -1 +0,0 @@
ALTER TABLE tasks ADD COLUMN status VARCHAR(255) NOT NULL DEFAULT 'pending';

173
index.php
View File

@ -1,33 +1,150 @@
<?php
$pageTitle = "Request Help";
include 'partials/header.php';
require_once __DIR__ . '/db/config.php';
declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
$pdo = db();
$stmt = $pdo->query('SELECT id, title, description, icon FROM tasks WHERE status = \'pending\' ORDER BY id DESC');
$tasks = $stmt->fetchAll();
$phpVersion = PHP_VERSION;
$now = date('Y-m-d H:i:s');
?>
<div class="hero text-center">
<h1 class="display-4">How can we help you today?</h1>
<p class="lead">Select a task from the options below to get started.</p>
</div>
<div class="container mt-5">
<div class="row g-4">
<?php foreach ($tasks as $task): ?>
<div class="col-lg-4 col-md-6">
<div class="action-card h-100">
<i data-feather="<?php echo htmlspecialchars($task['icon']); ?>" class="icon"></i>
<div class="card-body">
<h5 class="card-title"><?php echo htmlspecialchars($task['title']); ?></h5>
<p class="card-text"><?php echo htmlspecialchars($task['description']); ?></p>
<a href="#" class="btn btn-primary">Request Help</a>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>New Style</title>
<?php
// Read project preview data from environment
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
?>
<?php if ($projectDescription): ?>
<!-- Meta description -->
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
<!-- Open Graph meta tags -->
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<!-- Twitter meta tags -->
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<?php endif; ?>
<?php if ($projectImageUrl): ?>
<!-- Open Graph image -->
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<!-- Twitter image -->
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<?php endif; ?>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
<style>
:root {
--bg-color-start: #6a11cb;
--bg-color-end: #2575fc;
--text-color: #ffffff;
--card-bg-color: rgba(255, 255, 255, 0.01);
--card-border-color: rgba(255, 255, 255, 0.1);
}
body {
margin: 0;
font-family: 'Inter', sans-serif;
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
text-align: center;
overflow: hidden;
position: relative;
}
body::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
animation: bg-pan 20s linear infinite;
z-index: -1;
}
@keyframes bg-pan {
0% { background-position: 0% 0%; }
100% { background-position: 100% 100%; }
}
main {
padding: 2rem;
}
.card {
background: var(--card-bg-color);
border: 1px solid var(--card-border-color);
border-radius: 16px;
padding: 2rem;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
}
.loader {
margin: 1.25rem auto 1.25rem;
width: 48px;
height: 48px;
border: 3px solid rgba(255, 255, 255, 0.25);
border-top-color: #fff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.hint {
opacity: 0.9;
}
.sr-only {
position: absolute;
width: 1px; height: 1px;
padding: 0; margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap; border: 0;
}
h1 {
font-size: 3rem;
font-weight: 700;
margin: 0 0 1rem;
letter-spacing: -1px;
}
p {
margin: 0.5rem 0;
font-size: 1.1rem;
}
code {
background: rgba(0,0,0,0.2);
padding: 2px 6px;
border-radius: 4px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
footer {
position: absolute;
bottom: 1rem;
font-size: 0.8rem;
opacity: 0.7;
}
</style>
</head>
<body>
<main>
<div class="card">
<h1>Analyzing your requirements and generating your website…</h1>
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
<span class="sr-only">Loading…</span>
</div>
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
<p class="hint">This page will update automatically as the plan is implemented.</p>
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<?php include 'partials/footer.php'; ?>
</main>
<footer>
Page updated: <?= htmlspecialchars($now) ?> (UTC)
</footer>
</body>
</html>

View File

@ -1,88 +0,0 @@
<?php
session_start();
require_once __DIR__ . '/db/config.php';
$email = $password = '';
$errors = [];
// If user is already logged in, redirect to admin dashboard
if (isset($_SESSION['user_id'])) {
header("Location: admin/index.php");
exit;
}
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$email = trim($_POST['email']);
$password = $_POST['password'];
if (empty($email)) {
$errors['email'] = 'Email is required';
}
if (empty($password)) {
$errors['password'] = 'Password is required';
}
if (empty($errors)) {
try {
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$email]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password'])) {
$_SESSION['user_id'] = $user['id'];
$_SESSION['user_name'] = $user['name'];
$_SESSION['user_role'] = $user['role'];
header("Location: admin/index.php");
exit;
} else {
$errors['login'] = 'Invalid email or password';
}
} catch (PDOException $e) {
$errors['db'] = "Database error: " . $e->getMessage();
}
}
}
$pageTitle = "Login";
include 'partials/header.php';
?>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card mt-5">
<div class="card-body">
<h3 class="card-title text-center">Admin Login</h3>
<?php if (!empty($errors['login'])): ?>
<div class="alert alert-danger"><?php echo htmlspecialchars($errors['login']); ?></div>
<?php endif; ?>
<?php if (!empty($errors['db'])): ?>
<div class="alert alert-danger"><?php echo htmlspecialchars($errors['db']); ?></div>
<?php endif; ?>
<form method="POST" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
<div class="mb-3">
<label for="email" class="form-label">Email address</label>
<input type="email" class="form-control <?php echo !empty($errors['email']) ? 'is-invalid' : ''; ?>" id="email" name="email" value="<?php echo htmlspecialchars($email); ?>">
<?php if (!empty($errors['email'])): ?>
<div class="invalid-feedback"><?php echo $errors['email']; ?></div>
<?php endif; ?>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control <?php echo !empty($errors['password']) ? 'is-invalid' : ''; ?>" id="password" name="password">
<?php if (!empty($errors['password'])): ?>
<div class="invalid-feedback"><?php echo $errors['password']; ?></div>
<?php endif; ?>
</div>
<button type="submit" class="btn btn-primary w-100">Login</button>
</form>
</div>
</div>
</div>
</div>
</div>
<?php include 'partials/footer.php'; ?>

View File

@ -1,14 +0,0 @@
<div class="container">
<footer class="py-3 my-4">
<p class="text-center text-muted">&copy; <?php echo date('Y'); ?> OldHelp</p>
</footer>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script>
feather.replace()
</script>
<script src="assets/js/main.js"></script>
</body>
</html>

View File

@ -1,26 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?php echo isset($pageTitle) ? htmlspecialchars($pageTitle) : "OldHelp"; ?></title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="assets/css/custom.css" rel="stylesheet">
</head>
<body>
<header class="navbar navbar-expand-lg navbar-light bg-white py-3">
<div class="container">
<a class="navbar-brand" href="/"><strong>OldHelp</strong></a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/">Home</a>
</li>
</ul>
</div>
</div>
</header>