N7 finsh finsh
This commit is contained in:
parent
166c8cbdda
commit
dc54701498
67
accept-application.php
Normal file
67
accept-application.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
session_start();
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header("Location: /login.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
$application_id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
$user_id = $_SESSION['user_id'];
|
||||
|
||||
if (!$application_id) {
|
||||
header("Location: /index.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo = db();
|
||||
|
||||
// Begin a transaction
|
||||
$pdo->beginTransaction();
|
||||
|
||||
try {
|
||||
// Get application and task details, and ensure the current user owns the task
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT a.id as application_id, a.task_id, t.user_id as task_owner_id
|
||||
FROM applications a
|
||||
JOIN tasks t ON a.task_id = t.id
|
||||
WHERE a.id = ? AND t.user_id = ?"
|
||||
);
|
||||
$stmt->execute([$application_id, $user_id]);
|
||||
$application_info = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$application_info) {
|
||||
// If no result, either application doesn't exist or user doesn't own the task.
|
||||
throw new Exception("Authorization failed or application not found.");
|
||||
}
|
||||
|
||||
$task_id = $application_info['task_id'];
|
||||
|
||||
// 1. Update the accepted application's status to 'accepted'
|
||||
$stmt = $pdo->prepare("UPDATE applications SET status = 'accepted' WHERE id = ?");
|
||||
$stmt->execute([$application_id]);
|
||||
|
||||
// 2. Update the task's status to 'assigned'
|
||||
$stmt = $pdo->prepare("UPDATE tasks SET status = 'assigned' WHERE id = ?");
|
||||
$stmt->execute([$task_id]);
|
||||
|
||||
// 3. Reject all other pending applications for this task
|
||||
$stmt = $pdo->prepare("UPDATE applications SET status = 'rejected' WHERE task_id = ? AND id != ? AND status = 'pending'");
|
||||
$stmt->execute([$task_id, $application_id]);
|
||||
|
||||
// If all queries were successful, commit the transaction
|
||||
$pdo->commit();
|
||||
|
||||
header("Location: /task-details.php?id=" . $task_id . "&message=application_accepted");
|
||||
exit;
|
||||
|
||||
} catch (Exception $e) {
|
||||
// If any query fails, roll back the transaction
|
||||
$pdo->rollBack();
|
||||
error_log($e->getMessage());
|
||||
// Redirect with a generic error. Avoid exposing specific DB errors.
|
||||
header("Location: /task-details.php?id=" . ($task_id ?? 0) . "&message=acceptance_failed");
|
||||
exit;
|
||||
}
|
||||
@ -306,3 +306,46 @@ color: white;
|
||||
border-top: 1px solid #dee2e6;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
/* Manage Task Card Improvements */
|
||||
.task-manage-card {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.task-manage-card:hover {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.task-info h2 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.task-info h2 a {
|
||||
text-decoration: none;
|
||||
color: #0d6efd;
|
||||
}
|
||||
|
||||
.task-info p {
|
||||
margin-bottom: 0;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
.task-actions {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.btn-sm {
|
||||
padding: 0.25rem 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.task-card h3 a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
40
db/migrate.php
Normal file
40
db/migrate.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
function run_migrations() {
|
||||
$pdo = db();
|
||||
$log_file = __DIR__ . '/migrations.log';
|
||||
$migrations_dir = __DIR__ . '/migrations/';
|
||||
|
||||
if (!file_exists($log_file)) {
|
||||
touch($log_file);
|
||||
}
|
||||
|
||||
$executed_migrations = file($log_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
$all_migration_files = scandir($migrations_dir);
|
||||
|
||||
echo "Checking for new migrations...\n";
|
||||
|
||||
foreach ($all_migration_files as $file) {
|
||||
if (pathinfo($file, PATHINFO_EXTENSION) === 'sql') {
|
||||
if (!in_array($file, $executed_migrations)) {
|
||||
echo "Executing migration: $file...\n";
|
||||
$sql = file_get_contents($migrations_dir . $file);
|
||||
try {
|
||||
$pdo->exec($sql);
|
||||
file_put_contents($log_file, $file . PHP_EOL, FILE_APPEND);
|
||||
echo "Migration $file executed successfully.\n";
|
||||
} catch (PDOException $e) {
|
||||
echo "Error executing migration $file: " . $e->getMessage() . "\n";
|
||||
// Stop on error
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "All migrations are up to date.\n";
|
||||
}
|
||||
|
||||
run_migrations();
|
||||
|
||||
4
db/migrations.log
Normal file
4
db/migrations.log
Normal file
@ -0,0 +1,4 @@
|
||||
001_create_users_table.sql
|
||||
002_create_tasks_table.sql
|
||||
003_create_applications_table.sql
|
||||
004_add_whatsapp_to_users.sql
|
||||
1
db/migrations/004_add_whatsapp_to_users.sql
Normal file
1
db/migrations/004_add_whatsapp_to_users.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE users ADD COLUMN whatsapp_number VARCHAR(255) DEFAULT NULL;
|
||||
1
db/migrations/005_add_status_to_applications.sql
Normal file
1
db/migrations/005_add_status_to_applications.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE applications ADD COLUMN status VARCHAR(50) NOT NULL DEFAULT 'pending';
|
||||
50
delete-task.php
Normal file
50
delete-task.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header("Location: login.php");
|
||||
exit();
|
||||
}
|
||||
|
||||
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
|
||||
header("Location: manage-tasks.php?error=invalid_task_id");
|
||||
exit();
|
||||
}
|
||||
|
||||
$taskId = (int)$_GET['id'];
|
||||
$userId = $_SESSION['user_id'];
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
// First, verify the task belongs to the user
|
||||
$stmt = $pdo->prepare('SELECT user_id FROM tasks WHERE id = :task_id');
|
||||
$stmt->bindParam(':task_id', $taskId, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
$task = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$task || $task['user_id'] != $userId) {
|
||||
header("Location: manage-tasks.php?error=unauthorized");
|
||||
exit();
|
||||
}
|
||||
|
||||
// Delete applications for the task
|
||||
$stmt = $pdo->prepare('DELETE FROM applications WHERE task_id = :task_id');
|
||||
$stmt->bindParam(':task_id', $taskId, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
|
||||
// Delete the task
|
||||
$stmt = $pdo->prepare('DELETE FROM tasks WHERE id = :task_id');
|
||||
$stmt->bindParam(':task_id', $taskId, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
|
||||
header("Location: manage-tasks.php?success=task_deleted");
|
||||
exit();
|
||||
|
||||
} catch (PDOException $e) {
|
||||
// Log the error and redirect
|
||||
error_log("Delete task failed: " . $e->getMessage());
|
||||
header("Location: manage-tasks.php?error=db_error");
|
||||
exit();
|
||||
}
|
||||
@ -158,7 +158,7 @@ try {
|
||||
<?php else: ?>
|
||||
<?php foreach ($tasks as $task): ?>
|
||||
<div class="task-card">
|
||||
<h3><?= htmlspecialchars($task['title']) ?></h3>
|
||||
<h3><a href="task-details.php?id=<?= $task['id'] ?>"><?= htmlspecialchars($task['title']) ?></a></h3>
|
||||
<div class="task-meta">
|
||||
<span><?= htmlspecialchars($task['category']) ?> • <?= htmlspecialchars($task['location']) ?></span>
|
||||
<span>Posted by: <a href="profile.php?id=<?= $task['user_id_poster'] ?>"><strong><?= htmlspecialchars($task['user_name']) ?></strong></a></span>
|
||||
|
||||
@ -39,15 +39,18 @@ include 'shared/header.php';
|
||||
<?php else: ?>
|
||||
<div class="tasks-list">
|
||||
<?php foreach ($tasks as $task): ?>
|
||||
<a href="manage-task.php?id=<?php echo $task['id']; ?>" class="task-manage-card">
|
||||
<div class="task-manage-card">
|
||||
<div class="task-info">
|
||||
<h2><?php echo htmlspecialchars($task['title']); ?></h2>
|
||||
<h2><a href="manage-task.php?id=<?php echo $task['id']; ?>"><?php echo htmlspecialchars($task['title']); ?></a></h2>
|
||||
<p><?php echo htmlspecialchars(substr($task['description'], 0, 100)); ?>...</p>
|
||||
</div>
|
||||
<div class="task-status-manage">
|
||||
Status: <span class="status-badge status-<?php echo strtolower(htmlspecialchars($task['status'])); ?>"><?php echo htmlspecialchars($task['status']); ?></span>
|
||||
</div>
|
||||
</a>
|
||||
<div class="task-actions">
|
||||
<a href="delete-task.php?id=<?php echo $task['id']; ?>" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure you want to delete this task?');">Delete</a>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
46
profile.php
46
profile.php
@ -11,9 +11,23 @@ if (!$profileId) {
|
||||
|
||||
$pdo = db();
|
||||
|
||||
// Handle WhatsApp number update
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_SESSION['user_id']) && $_SESSION['user_id'] == $profileId) {
|
||||
$whatsapp_number = $_POST['whatsapp_number'] ?? '';
|
||||
try {
|
||||
$stmt = $pdo->prepare('UPDATE users SET whatsapp_number = :whatsapp_number WHERE id = :id');
|
||||
$stmt->execute([':whatsapp_number' => $whatsapp_number, ':id' => $profileId]);
|
||||
header("Location: profile.php?id=$profileId&message=whatsapp_updated");
|
||||
exit();
|
||||
} catch (PDOException $e) {
|
||||
$update_error = "Failed to update WhatsApp number.";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Fetch user information
|
||||
try {
|
||||
$stmt = $pdo->prepare('SELECT id, full_name, email, created_at FROM users WHERE id = :id');
|
||||
$stmt = $pdo->prepare('SELECT id, full_name, email, created_at, whatsapp_number FROM users WHERE id = :id');
|
||||
$stmt->execute([':id' => $profileId]);
|
||||
$profileUser = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
} catch (PDOException $e) {
|
||||
@ -56,11 +70,35 @@ include 'shared/header.php';
|
||||
<p><strong>Member Since:</strong> <?php echo date('F j, Y', strtotime($profileUser['created_at'])); ?></p>
|
||||
</div>
|
||||
|
||||
<?php if (isset($_GET['message']) && $_GET['message'] === 'whatsapp_updated'): ?>
|
||||
<div class="alert alert-success">Your WhatsApp number has been updated successfully.</div>
|
||||
<?php endif; ?>
|
||||
<?php if (isset($update_error)): ?>
|
||||
<div class="alert alert-danger"><?= htmlspecialchars($update_error) ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
|
||||
<?php if (isset($_SESSION['user_id']) && $_SESSION['user_id'] == $profileUser['id']): ?>
|
||||
<div class="card mb-4" style="margin-bottom: 2rem; background-color: #fff; border: 1px solid #dee2e6; border-radius: 0.75rem; padding: 1.5rem; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title" style="font-size: 1.75rem; margin-bottom: 1.5rem; border-bottom: 2px solid #dee2e6; padding-bottom: 0.5rem; color: #0d6efd;">My Contact Information</h2>
|
||||
<form action="profile.php?id=<?= $profileUser['id'] ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label for="whatsapp_number">WhatsApp Number</label>
|
||||
<input type="text" class="form-control" id="whatsapp_number" name="whatsapp_number" value="<?= htmlspecialchars($profileUser['whatsapp_number'] ?? '') ?>" placeholder="Enter your WhatsApp number...">
|
||||
<small class="form-text text-muted">This will only be shared with users whose applications you accept.</small>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" style="margin-top: 1rem;">Save</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
|
||||
<div class="profile-section">
|
||||
<h2>Posted Tasks</h2>
|
||||
<?php if (empty($postedTasks)): ?>
|
||||
<p><?php echo htmlspecialchars($profileUser['name']); ?> has not posted any tasks yet.</p>
|
||||
<p><?php echo htmlspecialchars($profileUser['full_name']); ?> has not posted any tasks yet.</p>
|
||||
<?php else: ?>
|
||||
<div class="task-list">
|
||||
<?php foreach ($postedTasks as $task):
|
||||
@ -68,7 +106,7 @@ include 'shared/header.php';
|
||||
$taskStatus = $task['status'] ?? 'unknown';
|
||||
?>
|
||||
<div class="task-card-profile">
|
||||
<h4><a href="manage-task.php?id=<?php echo $task['id']; ?>"><?php echo htmlspecialchars($task['title']); ?></a></h4>
|
||||
<h4><a href="task-details.php?id=<?php echo $task['id']; ?>"><?php echo htmlspecialchars($task['title']); ?></a></h4>
|
||||
<p><strong>Status:</strong> <span class="status-badge status-<?php echo strtolower(htmlspecialchars($taskStatus)); ?>"><?php echo htmlspecialchars($taskStatus); ?></span></p>
|
||||
<p><strong>Payout:</strong> $<?php echo htmlspecialchars($task['payout']); ?></p>
|
||||
</div>
|
||||
@ -80,7 +118,7 @@ include 'shared/header.php';
|
||||
<div class="profile-section">
|
||||
<h2>Completed Tasks</h2>
|
||||
<?php if (empty($completedTasks)): ?>
|
||||
<p><?php echo htmlspecialchars($profileUser['name']); ?> has not completed any tasks yet.</p>
|
||||
<p><?php echo htmlspecialchars($profileUser['full_name']); ?> has not completed any tasks yet.</p>
|
||||
<?php else: ?>
|
||||
<div class="task-list">
|
||||
<?php foreach ($completedTasks as $task):
|
||||
|
||||
118
task-details.php
Normal file
118
task-details.php
Normal file
@ -0,0 +1,118 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
session_start();
|
||||
require_once 'db/config.php';
|
||||
|
||||
$pdo = db();
|
||||
|
||||
$task_id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
|
||||
if (!$task_id) {
|
||||
header("Location: index.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Fetch task details along with owner's full name and whatsapp number
|
||||
$stmt = $pdo->prepare("SELECT t.*, u.full_name, u.whatsapp_number FROM tasks t JOIN users u ON t.user_id = u.id WHERE t.id = ?");
|
||||
$stmt->execute([$task_id]);
|
||||
$task = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$task) {
|
||||
header("Location: index.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
$is_owner = isset($_SESSION['user_id']) && $_SESSION['user_id'] == $task['user_id'];
|
||||
|
||||
$applications = [];
|
||||
if ($is_owner) {
|
||||
$stmt = $pdo->prepare("SELECT a.*, u.full_name FROM applications a JOIN users u ON a.user_id = u.id WHERE a.task_id = ? ORDER BY a.created_at DESC");
|
||||
$stmt->execute([$task_id]);
|
||||
$applications = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
$user_application = null;
|
||||
if (isset($_SESSION['user_id']) && !$is_owner) {
|
||||
$stmt = $pdo->prepare("SELECT * FROM applications WHERE task_id = ? AND user_id = ?");
|
||||
$stmt->execute([$task_id, $_SESSION['user_id']]);
|
||||
$user_application = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
$pageTitle = htmlspecialchars($task['title']);
|
||||
require_once 'shared/header.php';
|
||||
?>
|
||||
|
||||
<div class="container mt-5">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h1 class="card-title h3"><?php echo htmlspecialchars($task['title']); ?></h1>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p><strong>Posted by:</strong> <a href="profile.php?id=<?php echo $task['user_id']; ?>"><?php echo htmlspecialchars($task['full_name']); ?></a></p>
|
||||
<p><strong>Budget:</strong> $<?php echo htmlspecialchars(number_format((float)$task['budget'], 2)); ?></p>
|
||||
<hr>
|
||||
<p class="card-text"><?php echo nl2br(htmlspecialchars($task['description'])); ?></p>
|
||||
</div>
|
||||
<div class="card-footer text-muted">
|
||||
Posted on: <?php echo date('F j, Y, g:i a', strtotime($task['created_at'])); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($is_owner): ?>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3>Applicants</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?php if (empty($task['whatsapp_number'])): ?>
|
||||
<div class="alert alert-warning">Please <a href="/profile.php?id=<?= $_SESSION['user_id'] ?>">add your WhatsApp number</a> to your profile before accepting applications.</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (empty($applications)): ?>
|
||||
<p>No applications yet.</p>
|
||||
<?php else: ?>
|
||||
<ul class="list-group">
|
||||
<?php foreach ($applications as $application): ?>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<a href="/profile.php?id=<?= $application['user_id'] ?>"><?= htmlspecialchars($application['full_name']) ?></a>
|
||||
<span class="badge status-<?= htmlspecialchars($application['status']) ?>"><?= htmlspecialchars($application['status']) ?></span>
|
||||
</div>
|
||||
<?php if ($application['status'] === 'pending' && !empty($task['whatsapp_number'])): ?>
|
||||
<a href="accept-application.php?id=<?= $application['id'] ?>" class="btn btn-success btn-sm">Accept</a>
|
||||
<?php endif; ?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php elseif (isset($_SESSION['user_id'])): ?>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3>My Application</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?php if ($user_application): ?>
|
||||
<?php if ($user_application['status'] === 'accepted'): ?>
|
||||
<div class="alert alert-success">
|
||||
<h4>Congratulations! Your application was accepted.</h4>
|
||||
<p>Contact the task owner on WhatsApp: <strong><?= htmlspecialchars($task['whatsapp_number']) ?></strong></p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<p>Your application status is: <span class="badge status-<?= htmlspecialchars($user_application['status']) ?>"><?= htmlspecialchars($user_application['status']) ?></span></p>
|
||||
<?php endif; ?>
|
||||
<?php else: ?>
|
||||
<form action="apply.php" method="POST">
|
||||
<input type="hidden" name="task_id" value="<?= $task['id'] ?>">
|
||||
<button type="submit" class="btn btn-primary">Apply Now</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once 'shared/footer.php';
|
||||
?>
|
||||
Loading…
x
Reference in New Issue
Block a user