diff --git a/frontend/src/api/kanbanAPI.tsx b/frontend/src/api/kanbanAPI.tsx index b65a209..c9363a3 100644 --- a/frontend/src/api/kanbanAPI.tsx +++ b/frontend/src/api/kanbanAPI.tsx @@ -15,6 +15,24 @@ export default class KanbanAPI { return response.data as KanbanBoard[]; } + // Step 1: Create an empty board (no details yet) + static async createKanbanBoard(): Promise { + const token = localStorage.getItem("token"); + const response = await axios.post(`${API_URL}/kanbans`, {}, { + headers: { Authorization: `Bearer ${token}` }, + }); + return response.data as KanbanBoard; + } + + // Step 2: Use the returned board ID to populate the details + static async updateKanbanBoard(id: number, data: Partial): Promise { + const token = localStorage.getItem("token"); + const response = await axios.post(`${API_URL}/kanbans/${id}`, data, { + headers: { Authorization: `Bearer ${token}` }, + }); + return response.data as KanbanBoard; + } + static async getKanbanBoard(id: string): Promise { const token = localStorage.getItem("token"); const response = await axios.get(`${API_URL}/kanbans/${id}`, { @@ -25,6 +43,8 @@ export default class KanbanAPI { return response.data as KanbanBoard; } + + static getKanbanBoardsObservable(): Observable { return concat(of(0), interval(1000)).pipe( switchMap(() => from(KanbanAPI.getKanbanBoards())), @@ -44,4 +64,14 @@ export default class KanbanAPI { }) ); } + + // Add a function to delete a Kanban board + static async deleteKanbanBoard(id: number): Promise { + const token = localStorage.getItem("token"); + await axios.delete(`${API_URL}/kanbans/${id}`, { + headers: { Authorization: `Bearer ${token}` }, + }); + } + +} \ No newline at end of file diff --git a/frontend/src/components/buttons/button.tsx b/frontend/src/components/buttons/button.tsx index c527f5b..be3796e 100644 --- a/frontend/src/components/buttons/button.tsx +++ b/frontend/src/components/buttons/button.tsx @@ -2,17 +2,18 @@ import React from "react"; import { ButtonType } from "../../utilities/types"; type ButtonProps = { - type: ButtonType; + type?: ButtonType; // Make the type optional for non-submit buttons children: React.ReactNode; onClick?: () => void; + className?: string; }; -const Button = ({ type, children, onClick }: ButtonProps) => { +const Button = ({ type = "button", children, onClick, className = "" }: ButtonProps) => { return ( diff --git a/frontend/src/components/forms/add-board-form.tsx b/frontend/src/components/forms/add-board-form.tsx new file mode 100644 index 0000000..8862689 --- /dev/null +++ b/frontend/src/components/forms/add-board-form.tsx @@ -0,0 +1,85 @@ +import { useState, useEffect } from "react"; +import Button from "../buttons/button"; + +const AddBoardForm = ({ + isOpen, + onClose, + onSubmit, + defaultValues, +}: { + isOpen: boolean; + onClose: () => void; + onSubmit: (name: string, dueDate: string, description: string) => void; + defaultValues?: { name: string; dueDate: string; description: string }; +}) => { + const [name, setName] = useState(defaultValues?.name || ""); + const [dueDate, setDueDate] = useState(defaultValues?.dueDate || ""); + const [description, setDescription] = useState(defaultValues?.description || ""); + + useEffect(() => { + setName(defaultValues?.name || ""); + setDueDate(defaultValues?.dueDate || ""); + setDescription(defaultValues?.description || ""); + }, [defaultValues]); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + onSubmit(name, dueDate, description); + }; + + if (!isOpen) return null; + + return ( +
+
+
+

{defaultValues ? "Edit Board" : "Create New Board"}

+ +
+
+
+ + setName(e.target.value)} + placeholder="Enter board name" + className="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-400" + required + /> +
+
+ + setDueDate(e.target.value)} + className="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-400" + required + /> +
+
+ +