Files
coms3011a-lab1/components/Column.tsx

166 lines
3.9 KiB
TypeScript
Raw Normal View History

"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,
onArchive,
onEdit,
onStatusClick,
}: {
title: string;
tasks: Task[];
onAdd?: () => void;
onArchive: (task: Task) => void;
onEdit: (task: Task) => void;
onStatusClick: (task: Task) => void;
}) {
const [sortMode, setSortMode] = useState<SortMode>("none");
const [showMenu, setShowMenu] = useState(false);
const handleSort = (mode: SortMode) => {
setSortMode(mode);
setShowMenu(false);
};
const sortedTasks = [...tasks].sort((a, b) => {
if (sortMode === "topic") {
return a.topic.localeCompare(b.topic);
}
if (sortMode === "dueDate") {
return new Date(a.dueDate).getTime() - new Date(b.dueDate).getTime();
}
return 0;
});
return (
<div style={styles.column}>
<div style={styles.columnHeader}>
<h2 style={styles.columnTitle}>{title}</h2>
<div style={styles.headerActions}>
{onAdd && (
<button onClick={onAdd} style={styles.iconButton} title="Add Task">
+
</button>
)}
<div style={{ position: "relative" }}>
<button
onClick={() => setShowMenu(!showMenu)}
style={styles.iconButton}
title="Sort Tasks"
>
Sort
</button>
{showMenu && (
<div style={styles.dropdown}>
<button onClick={() => handleSort("topic")} style={styles.dropdownItem}>
Sort by Topic
</button>
<button onClick={() => handleSort("dueDate")} style={styles.dropdownItem}>
Sort by Due Date
</button>
<button onClick={() => handleSort("none")} style={styles.dropdownItem}>
Clear Sorting
</button>
</div>
)}
</div>
</div>
</div>
{sortMode !== "none" && (
<div style={styles.sortLabel}>
Currently sorted by: {sortMode === "topic" ? "Topic" : "Due Date"}
</div>
)}
{sortedTasks.map((task) => (
<TaskCard
key={task.id}
task={task}
onArchive={onArchive}
onEdit={onEdit}
onStatusClick={onStatusClick}
/>
))}
</div>
);
}
const styles = {
column: {
background: "#f8fafc",
padding: "15px",
borderRadius: "12px",
flex: 1,
minHeight: "65vh",
maxHeight: "65vh",
overflowY: "auto" as const,
boxShadow: "0 10px 25px rgba(0,0,0,0.1)",
},
columnHeader: {
display: "flex",
justifyContent: "space-between",
alignItems: "center",
marginBottom: "15px",
},
columnTitle: {
color: "#0f172a",
fontWeight: "700",
fontSize: "25px",
margin: 0,
},
iconButton: {
background: "transparent",
border: "none",
color: "#0f172a",
fontSize: "16px",
fontWeight: "700",
cursor: "pointer",
padding: "0",
display: "flex",
alignItems: "center",
justifyContent: "center",
},
headerActions: {
display: "flex",
gap: "10px",
alignItems: "center",
},
sortLabel: {
fontSize: "13px",
opacity: 0.7,
marginBottom: "10px",
fontStyle: "italic",
color: "#0f172a",
},
dropdown: {
position: "absolute" as const,
top: "30px",
right: 0,
background: "#f8fafc",
border: "1px solid #cbd5e1",
borderRadius: "8px",
boxShadow: "0 5px 15px rgba(0,0,0,0.1)",
display: "flex",
flexDirection: "column" as const,
zIndex: 100,
},
dropdownItem: {
padding: "8px 12px",
background: "transparent",
border: "none",
textAlign: "left" as const,
cursor: "pointer",
fontSize: "14px",
color: "#0f172a",
},
};