02_04_japtodo/Jap Robertus K.S - 5803024004 Tugas Praktikum Back End Programming Week 2.php
5803024004 e3b99a1942 Upload files to "/"
Jap Robertus K.S - 5803024004 Tugas Week 2 Praktikum Back End To Do Task App
2025-08-27 06:14:17 -04:00

651 lines
22 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
// setup database nya
$host = 'localhost';
$username = 'root';
$password = '';
$database = 'todo_app';
// koneksi
$conn = new mysqli($host, $username, $password);
// cek koneksi
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
//ngebuat database kalo blm ada
$sql = "CREATE DATABASE IF NOT EXISTS $database";
if ($conn->query($sql) === TRUE) {
$conn->select_db($database);
// buat tabel
$createGroupsTable = "CREATE TABLE IF NOT EXISTS groups (
group_id INT AUTO_INCREMENT PRIMARY KEY,
group_name VARCHAR(255) NOT NULL
)";
$conn->query($createGroupsTable);
// buat tabel task
$createTasksTable = "CREATE TABLE IF NOT EXISTS tasks (
task_id INT AUTO_INCREMENT PRIMARY KEY,
task_name VARCHAR(255) NOT NULL,
task_description TEXT,
group_id INT,
is_done BOOLEAN DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (group_id) REFERENCES groups(group_id) ON DELETE CASCADE
)";
$conn->query($createTasksTable);
} else {
die("Error creating database: " . $conn->error);
}
// buat submissions
if ($_POST) {
if (isset($_POST['add_group'])) {
$group_name = $_POST['group_name'];
$stmt = $conn->prepare("INSERT INTO groups (group_name) VALUES (?)");
$stmt->bind_param("s", $group_name);
$stmt->execute();
$stmt->close();
}
if (isset($_POST['add_task'])) {
$task_name = $_POST['task_name'];
$task_description = $_POST['task_description'];
$group_id = $_POST['group_id'];
$stmt = $conn->prepare("INSERT INTO tasks (task_name, task_description, group_id) VALUES (?, ?, ?)");
$stmt->bind_param("ssi", $task_name, $task_description, $group_id);
$stmt->execute();
$stmt->close();
}
if (isset($_POST['update_task'])) {
$task_id = $_POST['task_id'];
$task_name = $_POST['task_name'];
$task_description = $_POST['task_description'];
$group_id = $_POST['group_id'];
$stmt = $conn->prepare("UPDATE tasks SET task_name=?, task_description=?, group_id=? WHERE task_id=?");
$stmt->bind_param("ssii", $task_name, $task_description, $group_id, $task_id);
$stmt->execute();
$stmt->close();
}
if (isset($_POST['toggle_task'])) {
$task_id = $_POST['task_id'];
$is_done = $_POST['is_done'];
$stmt = $conn->prepare("UPDATE tasks SET is_done=? WHERE task_id=?");
$stmt->bind_param("ii", $is_done, $task_id);
$stmt->execute();
$stmt->close();
}
if (isset($_POST['delete_task'])) {
$task_id = $_POST['task_id'];
$stmt = $conn->prepare("DELETE FROM tasks WHERE task_id=?");
$stmt->bind_param("i", $task_id);
$stmt->execute();
$stmt->close();
}
if (isset($_POST['delete_group'])) {
$group_id = $_POST['group_id'];
$stmt = $conn->prepare("DELETE FROM groups WHERE group_id=?");
$stmt->bind_param("i", $group_id);
$stmt->execute();
$stmt->close();
}
header("Location: " . $_SERVER['PHP_SELF']);
exit();
}
$edit_task = null;
if (isset($_GET['edit'])) {
$task_id = $_GET['edit'];
$result = $conn->query("SELECT * FROM tasks WHERE task_id = $task_id");
$edit_task = $result->fetch_assoc();
}
$groups_result = $conn->query("SELECT * FROM groups ORDER BY group_name");
$groups = [];
while ($row = $groups_result->fetch_assoc()) {
$groups[] = $row;
}
$tasks_result = $conn->query("
SELECT t.*, g.group_name
FROM tasks t
LEFT JOIN groups g ON t.group_id = g.group_id
ORDER BY g.group_name, t.created_at DESC
");
$tasks = [];
while ($row = $tasks_result->fetch_assoc()) {
$tasks[$row['group_id']][] = $row;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Task Manager</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.main-header {
text-align: center;
margin-bottom: 40px;
}
.main-header h1 {
color: white;
font-size: 2.5rem;
font-weight: 300;
text-shadow: 0 2px 4px rgba(0,0,0,0.3);
margin-bottom: 10px;
}
.main-header p {
color: rgba(255,255,255,0.8);
font-size: 1.1rem;
}
.container {
max-width: 1000px;
margin: 0 auto;
}
.top-actions {
display: flex;
gap: 20px;
margin-bottom: 40px;
}
.action-card {
flex: 1;
background: white;
border-radius: 15px;
padding: 25px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
backdrop-filter: blur(10px);
}
.action-card h3 {
color: #2c3e50;
font-size: 1.3rem;
margin-bottom: 20px;
display: flex;
align-items: center;
gap: 10px;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #34495e;
font-size: 14px;
}
input, textarea, select {
width: 100%;
padding: 12px 15px;
border: 2px solid #e9ecef;
border-radius: 10px;
font-size: 14px;
transition: all 0.3s ease;
background-color: #f8f9fa;
}
input:focus, textarea:focus, select:focus {
outline: none;
border-color: #667eea;
background-color: white;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
textarea {
height: 80px;
resize: vertical;
}
.btn {
padding: 12px 24px;
border: none;
border-radius: 25px;
cursor: pointer;
font-size: 14px;
font-weight: 600;
transition: all 0.3s ease;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.btn-primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
}
.btn-danger {
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%);
color: white;
}
.btn-danger:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(238, 90, 82, 0.4);
}
.btn-warning {
background: linear-gradient(135deg, #feca57 0%, #ff9ff3 100%);
color: white;
}
.btn-warning:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(254, 202, 87, 0.4);
}
.btn-small {
padding: 6px 12px;
font-size: 12px;
margin: 3px;
}
.groups-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 25px;
}
.group-card {
background: white;
border-radius: 20px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(0,0,0,0.15);
transition: transform 0.3s ease;
}
.group-card:hover {
transform: translateY(-5px);
}
.group-header {
background: linear-gradient(135deg, #2c3e50 0%, #3498db 100%);
color: white;
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.group-header h3 {
margin: 0;
font-size: 1.4rem;
font-weight: 500;
}
.task-count {
background: rgba(255,255,255,0.2);
padding: 4px 12px;
border-radius: 15px;
font-size: 12px;
font-weight: 600;
}
.tasks-container {
padding: 20px;
max-height: 400px;
overflow-y: auto;
}
.task-item {
background: #f8f9fa;
padding: 18px;
margin-bottom: 15px;
border-radius: 12px;
border-left: 4px solid #667eea;
transition: all 0.3s ease;
}
.task-item:hover {
background: #e9ecef;
transform: translateX(5px);
}
.task-item.done {
opacity: 0.6;
border-left-color: #95a5a6;
background: #ecf0f1;
}
.task-item.done .task-title {
text-decoration: line-through;
}
.task-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 12px;
}
.task-title {
font-weight: 600;
color: #2c3e50;
font-size: 1.1rem;
flex: 1;
}
.task-status {
font-size: 1.2rem;
margin-left: 10px;
}
.task-description {
color: #7f8c8d;
margin-bottom: 15px;
font-size: 14px;
line-height: 1.4;
}
.task-meta {
font-size: 12px;
color: #95a5a6;
margin-bottom: 15px;
}
.task-actions {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.no-content {
text-align: center;
color: #7f8c8d;
padding: 40px 20px;
font-style: italic;
}
.no-content .icon {
font-size: 3rem;
margin-bottom: 10px;
display: block;
}
.edit-banner {
background: linear-gradient(135deg, #f39c12 0%, #e67e22 100%);
color: white;
padding: 15px;
border-radius: 10px;
margin-bottom: 20px;
text-align: center;
font-weight: 600;
}
@media (max-width: 768px) {
.top-actions {
flex-direction: column;
}
.groups-container {
grid-template-columns: 1fr;
}
.main-header h1 {
font-size: 2rem;
}
.task-actions {
flex-direction: column;
}
.task-header {
flex-direction: column;
align-items: flex-start;
}
.task-status {
margin-left: 0;
margin-top: 5px;
}
}
/* Custom scrollbar */
.tasks-container::-webkit-scrollbar {
width: 6px;
}
.tasks-container::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 3px;
}
.tasks-container::-webkit-scrollbar-thumb {
background: #bdc3c7;
border-radius: 3px;
}
.tasks-container::-webkit-scrollbar-thumb:hover {
background: #95a5a6;
}
</style>
</head>
<body>
<div class="main-header">
<h1>📋 Task Manager</h1>
<p>Kelola Tugas Mu Dengan Efisien Dan Membantu Tingkatkan Produktifitasmu</p>
</div>
<div class="container">
<?php if ($edit_task): ?>
<div class="edit-banner">
✏️ Currently editing task: "<?= htmlspecialchars($edit_task['task_name']) ?>"
</div>
<?php endif; ?>
<div class="top-actions">
<!-- Add Group Form -->
<div class="action-card">
<h3>
<span>📁</span>
Create New Group
</h3>
<form method="POST">
<div class="form-group">
<label for="group_name">Group Name</label>
<input type="text" id="group_name" name="group_name" required
placeholder="e.g., Work, Personal, Shopping">
</div>
<button type="submit" name="add_group" class="btn btn-primary">
Create Group
</button>
</form>
</div>
<!-- Add/Edit Task Form -->
<div class="action-card">
<h3>
<span><?= $edit_task ? '✏️' : '' ?></span>
<?= $edit_task ? 'Edit Task' : 'Add New Task' ?>
</h3>
<form method="POST">
<?php if ($edit_task): ?>
<input type="hidden" name="task_id" value="<?= $edit_task['task_id'] ?>">
<?php endif; ?>
<div class="form-group">
<label for="task_name">Task Name</label>
<input type="text" id="task_name" name="task_name" required
placeholder="What needs to be done?"
value="<?= $edit_task ? htmlspecialchars($edit_task['task_name']) : '' ?>">
</div>
<div class="form-group">
<label for="task_description">Description (Optional)</label>
<textarea id="task_description" name="task_description"
placeholder="Add more details about this task..."><?= $edit_task ? htmlspecialchars($edit_task['task_description']) : '' ?></textarea>
</div>
<div class="form-group">
<label for="group_id">Select Group</label>
<select id="group_id" name="group_id" required>
<option value="">Choose a group...</option>
<?php foreach ($groups as $group): ?>
<option value="<?= $group['group_id'] ?>"
<?= ($edit_task && $edit_task['group_id'] == $group['group_id']) ? 'selected' : '' ?>>
<?= htmlspecialchars($group['group_name']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<button type="submit" name="<?= $edit_task ? 'update_task' : 'add_task' ?>" class="btn btn-primary">
<?= $edit_task ? 'Update Task' : 'Add Task' ?>
</button>
<?php if ($edit_task): ?>
<a href="<?= $_SERVER['PHP_SELF'] ?>">
<button type="button" class="btn btn-warning">Cancel Edit</button>
</a>
<?php endif; ?>
</form>
</div>
</div>
<!-- Groups and Tasks Display -->
<div class="groups-container">
<?php if (empty($groups)): ?>
<div class="no-content">
<span class="icon">📭</span>
<h3>Belum ada Group!</h3>
<p>Buat Group dulu lalu tambahkan task!.</p>
</div>
<?php else: ?>
<?php foreach ($groups as $group): ?>
<div class="group-card">
<div class="group-header">
<div>
<h3><?= htmlspecialchars($group['group_name']) ?></h3>
<div class="task-count">
<?= count($tasks[$group['group_id']] ?? []) ?> tasks
</div>
</div>
<form method="POST" style="display: inline;"
onsubmit="return confirm('Delete this group and all its tasks?')">
<input type="hidden" name="group_id" value="<?= $group['group_id'] ?>">
<button type="submit" name="delete_group" class="btn btn-danger btn-small">
🗑️ Delete
</button>
</form>
</div>
<div class="tasks-container">
<?php if (empty($tasks[$group['group_id']])): ?>
<div class="no-content">
<span class="icon">✨</span>
<p>No tasks in this group yet.<br>Add your first task above!</p>
</div>
<?php else: ?>
<?php foreach ($tasks[$group['group_id']] as $task): ?>
<div class="task-item <?= $task['is_done'] ? 'done' : '' ?>">
<div class="task-header">
<div class="task-title">
<?= htmlspecialchars($task['task_name']) ?>
</div>
<div class="task-status">
<?= $task['is_done'] ? '✅' : '⏳' ?>
</div>
</div>
<?php if ($task['task_description']): ?>
<div class="task-description">
<?= htmlspecialchars($task['task_description']) ?>
</div>
<?php endif; ?>
<div class="task-meta">
Created: <?= date('M d, Y \a\t H:i', strtotime($task['created_at'])) ?>
</div>
<div class="task-actions">
<!-- Toggle Status -->
<form method="POST" style="display: inline;">
<input type="hidden" name="task_id" value="<?= $task['task_id'] ?>">
<input type="hidden" name="is_done" value="<?= $task['is_done'] ? 0 : 1 ?>">
<button type="submit" name="toggle_task" class="btn btn-primary btn-small">
<?= $task['is_done'] ? '↩️ Undo' : '✅ Done' ?>
</button>
</form>
<!-- Edit -->
<a href="?edit=<?= $task['task_id'] ?>">
<button type="button" class="btn btn-warning btn-small">✏️ Edit</button>
</a>
<!-- Delete -->
<form method="POST" style="display: inline;"
onsubmit="return confirm('Delete this task?')">
<input type="hidden" name="task_id" value="<?= $task['task_id'] ?>">
<button type="submit" name="delete_task" class="btn btn-danger btn-small">
🗑️ Delete
</button>
</form>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
<script>
// Auto-focus on task name when editing
<?php if ($edit_task): ?>
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('task_name').focus();
document.getElementById('task_name').select();
});
<?php endif; ?>
// Smooth scroll to edited task
if (window.location.hash) {
setTimeout(() => {
document.querySelector(window.location.hash)?.scrollIntoView({
behavior: 'smooth'
});
}, 100);
}
</script>
</body>
</html>
<?php
$conn->close();
?>