From f7efd57a859c3d6be866307cf1d9020a881f0268 Mon Sep 17 00:00:00 2001 From: Mpho10111 Date: Wed, 5 Aug 2026 01:10:09 +0200 Subject: [PATCH] feat: add sort and tick to dashboard UI --- app/dashboard/page.tsx | 150 ++--------------- app/globals.css | 51 +++--- components/AddTaskForm.tsx | 183 +++++++++++++++++++++ components/Board.tsx | 36 +++++ components/Column.tsx | 318 +++++++++++++++++++++++++++++++++++++ components/TaskCard.tsx | 0 6 files changed, 581 insertions(+), 157 deletions(-) create mode 100644 components/AddTaskForm.tsx create mode 100644 components/Board.tsx create mode 100644 components/Column.tsx create mode 100644 components/TaskCard.tsx diff --git a/app/dashboard/page.tsx b/app/dashboard/page.tsx index 0170353..a3fead6 100644 --- a/app/dashboard/page.tsx +++ b/app/dashboard/page.tsx @@ -1,6 +1,8 @@ "use client"; import { useState } from "react"; +import Column from "@/components/Column"; +import AddTaskForm from "@/components/AddTaskForm"; export default function Dashboard() { const [tasks, setTasks] = useState({ @@ -22,19 +24,12 @@ export default function Dashboard() { done: [], }); - const addTask = () => { - const title = prompt("Task title:"); - if (!title) return; - - const description = prompt("Description:") || ""; - const dueDate = prompt("Due date (YYYY-MM-DD):") || ""; - const topic = prompt("Topic:") || ""; - - const newTask = { title, description, dueDate, topic }; + const [showForm, setShowForm] = useState(false); + const addTask = (task: any) => { setTasks((prev) => ({ ...prev, - todo: [...prev.todo, newTask], + todo: [...prev.todo, task], })); }; @@ -43,70 +38,27 @@ export default function Dashboard() {

Planner Danner

- + setShowForm(true)} />
+ + {showForm && ( + setShowForm(false)} + /> + )} ); } -function Column({ - title, - tasks, - onAdd, -}: { - title: string; - tasks: any[]; - onAdd?: () => void; -}) { - return ( -
-
-

{title}

- -
- {onAdd && ( - - )} - - {/* ✅ FIXED: sort now uses SAME button style */} - - - -
-
- - {tasks.map((task, index) => ( -
-
-
{task.title}
- - {/* same exact style */} - -
- -
- {task.description.slice(0, 30)} - {task.description.length > 30 && "..."} -
- -
📅 {task.dueDate}
-
- ))} -
- ); -} - const styles = { container: { minHeight: "100vh", background: "linear-gradient(to bottom, #38bdf8, #0ea5e9)", padding: "30px", }, - title: { textAlign: "center" as const, fontSize: "90px", @@ -119,84 +71,10 @@ const styles = { `, marginBottom: "30px", }, - board: { display: "flex", gap: "20px", justifyContent: "center", }, +}; - column: { - background: "#f8fafc", - padding: "15px", - borderRadius: "12px", - flex: 1, - minHeight: "65vh", - maxHeight: "65vh", - overflowY: "auto", - 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, - }, - - /* ✅ SINGLE SOURCE OF TRUTH FOR ALL ICONS */ - iconButton: { - background: "transparent", - border: "none", - color: "#0f172a", - fontSize: "22px", - fontWeight: "600", - cursor: "pointer", - padding: "0", - }, - - headerActions: { - display: "flex", - gap: "10px", - alignItems: "center", - }, - - card: { - background: "#dae4f0", - padding: "18px", - borderRadius: "12px", - marginBottom: "15px", - color: "#0f172a", - fontSize: "16px", - }, - - cardHeader: { - display: "flex", - justifyContent: "space-between", - alignItems: "center", - marginBottom: "6px", - }, - - cardTitle: { - fontWeight: "700", - marginBottom: "6px", - }, - - cardDescription: { - fontSize: "13px", - opacity: 0.7, - marginBottom: "8px", - }, - - cardDate: { - fontSize: "12px", - opacity: 0.6, - }, -}; \ No newline at end of file diff --git a/app/globals.css b/app/globals.css index a2dc41e..dfb35d2 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1,26 +1,35 @@ -@import "tailwindcss"; - :root { - --background: #ffffff; - --foreground: #171717; -} - -@theme inline { - --color-background: var(--background); - --color-foreground: var(--foreground); - --font-sans: var(--font-geist-sans); - --font-mono: var(--font-geist-mono); -} - -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } + --primary-bg: linear-gradient(to bottom, #38bdf8, #0ea5e9); + --card-bg: #dae4f0; + --text-dark: #0f172a; + --text-light: #e0f2fe; + --accent: #0284c7; } body { - background: var(--background); - color: var(--foreground); - font-family: Arial, Helvetica, sans-serif; + font-family: 'Inter', sans-serif; + margin: 0; + padding: 0; + background: var(--primary-bg); } + +h1, h2, h3 { + font-weight: 900; + letter-spacing: 2px; +} + +/* ✅ Consistent placeholder styling */ +input::placeholder, +textarea::placeholder { + color: #6b7280; /* same grey as Title/Description */ + font-family: inherit; + font-size: 14px; +} + +/* ✅ Style the dropdown placeholder option */ +select option[value=""] { + color: #6b7280; /* same grey */ + font-family: inherit; + font-size: 14px; +} + diff --git a/components/AddTaskForm.tsx b/components/AddTaskForm.tsx new file mode 100644 index 0000000..318b808 --- /dev/null +++ b/components/AddTaskForm.tsx @@ -0,0 +1,183 @@ +"use client"; + +import { useState } from "react"; + +export default function AddTaskForm({ + onSubmit, + onClose, +}: { + onSubmit: (task: any) => void; + onClose: () => void; +}) { + const [formData, setFormData] = useState({ + title: "", + description: "", + dueDate: "", + topic: "", + }); + + const handleChange = ( + e: React.ChangeEvent + ) => { + setFormData({ ...formData, [e.target.name]: e.target.value }); + }; + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + if (!formData.topic) { + alert("Please select a topic before saving."); + return; + } + onSubmit(formData); + onClose(); + }; + + return ( +
+
+

Add New Task

+
+ +