feat: connect task board and status workflow

This commit is contained in:
Mpho10111
2026-08-11 20:56:13 +02:00
parent 53ecfa4caf
commit b4029ad65a
3 changed files with 437 additions and 246 deletions

View File

@@ -1,42 +1,30 @@
"use client";
import { useState } from "react";
import type { Task } from "@/types/task";
import TaskCard from "./TaskCard";
type SortMode = "none" | "topic" | "dueDate";
export default function Column({
title,
tasks,
onAdd,
onStatusChange,
onArchive,
onEdit,
onStatusClick,
}: {
title: string;
tasks: any[];
tasks: Task[];
onAdd?: () => void;
onStatusChange?: (index: number, newStatus: "Todo" | "In-Progress" | "Complete") => void;
onArchive: (task: Task) => void;
onEdit: (task: Task) => void;
onStatusClick: (task: Task) => void;
}) {
const [popupTaskIndex, setPopupTaskIndex] = useState<number | null>(null);
const [sortMode, setSortMode] = useState<"none" | "topic" | "dueDate">("none");
const [sortMode, setSortMode] = useState<SortMode>("none");
const [showMenu, setShowMenu] = useState(false);
const handleCircleClick = (index: number) => {
const task = tasks[index];
if (task.status !== "Complete") {
setPopupTaskIndex(index);
}
};
const handleConfirm = (yes: boolean) => {
if (popupTaskIndex !== null && onStatusChange) {
const task = tasks[popupTaskIndex];
if (task.status === "Todo" && yes) {
onStatusChange(popupTaskIndex, "In-Progress");
} else if (task.status === "In-Progress" && yes) {
onStatusChange(popupTaskIndex, "Complete");
}
}
setPopupTaskIndex(null);
};
const handleSort = (mode: "none" | "topic" | "dueDate") => {
const handleSort = (mode: SortMode) => {
setSortMode(mode);
setShowMenu(false);
};
@@ -62,14 +50,13 @@ export default function Column({
</button>
)}
{/* Sort button */}
<div style={{ position: "relative" }}>
<button
onClick={() => setShowMenu(!showMenu)}
style={styles.iconButton}
title="Sort Tasks"
>
Sort
</button>
{showMenu && (
<div style={styles.dropdown}>
@@ -85,8 +72,6 @@ export default function Column({
</div>
)}
</div>
<button style={styles.iconButton} title="More Options"></button>
</div>
</div>
@@ -96,57 +81,15 @@ export default function Column({
</div>
)}
{sortedTasks.map((task, index) => (
<div key={index} style={styles.card}>
<div style={styles.cardHeader}>
{/* Hollow circle */}
<div
style={{
...styles.circle,
cursor: task.status === "Complete" ? "default" : "pointer",
}}
onClick={() => handleCircleClick(index)}
title="Change Status"
>
{task.status === "In-Progress" || task.status === "Complete" ? "✔" : ""}
</div>
<div style={styles.cardTitle}>{task.title}</div>
<button style={styles.iconButton}></button>
</div>
<div style={styles.cardDescription}>
{task.description.slice(0, 30)}
{task.description.length > 30 && "..."}
</div>
<div style={styles.cardDate}>📅 {task.dueDate}</div>
{task.topic && (
<div style={styles.cardTopic}>
<em>{task.topic}</em>
</div>
)}
</div>
{sortedTasks.map((task) => (
<TaskCard
key={task.id}
task={task}
onArchive={onArchive}
onEdit={onEdit}
onStatusClick={onStatusClick}
/>
))}
{/* Popup */}
{popupTaskIndex !== null && (
<div style={styles.overlay}>
<div style={styles.modal}>
<h3 style={styles.title}>
{tasks[popupTaskIndex].status === "Todo"
? "Are you ready to start the task?"
: "Have you finished this task?"}
</h3>
<div style={styles.actions}>
<button onClick={() => handleConfirm(true)} style={styles.saveButton}>
Yes
</button>
<button onClick={() => handleConfirm(false)} style={styles.cancelButton}>
No
</button>
</div>
</div>
</div>
)}
</div>
);
}
@@ -178,8 +121,8 @@ const styles = {
background: "transparent",
border: "none",
color: "#0f172a",
fontSize: "22px",
fontWeight: "600",
fontSize: "16px",
fontWeight: "700",
cursor: "pointer",
padding: "0",
display: "flex",
@@ -198,102 +141,6 @@ const styles = {
fontStyle: "italic",
color: "#0f172a",
},
card: {
background: "#dae4f0",
padding: "18px",
borderRadius: "12px",
marginBottom: "15px",
color: "#0f172a",
fontSize: "16px",
},
cardHeader: {
display: "flex",
justifyContent: "space-between",
alignItems: "center",
marginBottom: "6px",
gap: "10px",
},
cardTitle: {
fontWeight: "700",
flex: 1,
},
cardDescription: {
fontSize: "13px",
opacity: 0.7,
marginBottom: "8px",
},
cardDate: {
fontSize: "12px",
opacity: 0.6,
},
cardTopic: {
fontSize: "12px",
opacity: 0.7,
textAlign: "right" as const,
marginTop: "6px",
fontStyle: "italic",
},
circle: {
width: "20px",
height: "20px",
border: "2px solid black",
borderRadius: "50%",
display: "flex",
alignItems: "center",
justifyContent: "center",
fontSize: "14px",
fontWeight: "bold",
backgroundColor: "white",
},
overlay: {
position: "fixed" as const,
top: 0,
left: 0,
width: "100%",
height: "100%",
background: "rgba(0,0,0,0.4)",
display: "flex",
justifyContent: "center",
alignItems: "center",
zIndex: 1000,
},
modal: {
background: "#f8fafc",
padding: "25px",
borderRadius: "12px",
boxShadow: "0 10px 25px rgba(0,0,0,0.2)",
width: "300px",
textAlign: "center" as const,
},
title: {
marginBottom: "15px",
fontSize: "18px",
fontWeight: "600",
color: "#0f172a",
},
actions: {
display: "flex",
justifyContent: "space-between",
marginTop: "15px",
},
saveButton: {
background: "#0ea5e9",
color: "white",
border: "none",
padding: "8px 16px",
borderRadius: "8px",
cursor: "pointer",
fontWeight: "600",
},
cancelButton: {
background: "#e2e8f0",
color: "#0f172a",
border: "none",
padding: "8px 16px",
borderRadius: "8px",
cursor: "pointer",
fontWeight: "600",
},
dropdown: {
position: "absolute" as const,
top: "30px",
@@ -315,4 +162,4 @@ const styles = {
fontSize: "14px",
color: "#0f172a",
},
};
};