diff --git a/src/app/boards/components/ImportBoardsForm.tsx b/src/app/boards/components/ImportBoardsForm.tsx new file mode 100644 index 00000000..7f39051e --- /dev/null +++ b/src/app/boards/components/ImportBoardsForm.tsx @@ -0,0 +1,196 @@ +"use client"; + +import { Fragment, useState } from "react"; +import { api } from "~/trpc/react"; +import { Listbox, Transition } from "@headlessui/react"; + +import { FaTrello } from "react-icons/fa"; +import { HiChevronUpDown, HiXMark } from "react-icons/hi2"; + +import { useModal } from "~/app/providers/modal"; + +import { useFormik } from "formik"; + +interface TrelloFormValues { + apiKey: string; + token: string; +} + +const sources = [{ source: "Trello" }]; + +const SelectSource = ({ handleNextStep }: { handleNextStep: () => void }) => { + const formik = useFormik({ + initialValues: { + source: "Trello", + }, + onSubmit: () => { + handleNextStep(); + }, + }); + + return ( +
+ + + {({ open }) => ( + <> +
+ + + + + {formik.values.source} + + + + + + + + + {sources.map(({ source }, index) => ( + + {() => ( +
+ + + {source} + +
+ )} +
+ ))} +
+
+
+ + )} +
+
+ +
+
+ ); +}; + +interface ImportTrelloProps { + handleSetAuthDetails: (apiKey: string, token: string) => void; +} + +const ImportTrello: React.FC = ({ + handleSetAuthDetails, +}) => { + const formik = useFormik({ + initialValues: { + apiKey: "", + token: "", + }, + onSubmit: (values: TrelloFormValues) => { + handleSetAuthDetails(values.apiKey, values.token); + }, + }); + + return ( +
+ + + + +
+ +
+
+ ); +}; + +export function ImportBoardsForm() { + // const utils = api.useUtils(); + const { closeModal } = useModal(); + const [step, setStep] = useState(1); + const [apiKey, setApiKey] = useState(""); + const [token, setToken] = useState(""); + + const boards = api.import.trello.getBoards.useQuery( + { apiKey, token }, + { + enabled: apiKey && token ? true : false, + }, + ); + + const handleSetAuthDetails = (apiKey: string, token: string) => { + setApiKey(apiKey); + setToken(token); + }; + + // const refetchBoards = () => utils.board.all.refetch(); + + return ( + <> +
+

New import

+ +
+ + {step === 1 && setStep(step + 1)} />} + {step === 2 && ( + + )} + + ); +} diff --git a/src/app/boards/page.tsx b/src/app/boards/page.tsx index 100769c4..9c5de9d4 100644 --- a/src/app/boards/page.tsx +++ b/src/app/boards/page.tsx @@ -1,15 +1,16 @@ "use client"; -import { HiOutlinePlusSmall } from "react-icons/hi2"; +import { HiArrowDownTray, HiOutlinePlusSmall } from "react-icons/hi2"; import { BoardsList } from "./components/BoardsList"; import { useModal } from "~/app/providers/modal"; import Modal from "~/app/components/modal"; +import { ImportBoardsForm } from "~/app/boards/components/ImportBoardsForm"; import { NewBoardForm } from "~/app/boards/components/NewBoardForm"; export default function BoardsPage() { - const { openModal } = useModal(); + const { openModal, modalContentType } = useModal(); return (
@@ -18,22 +19,35 @@ export default function BoardsPage() { Boards
+
- + {modalContentType === "NEW_BOARD" && } + {modalContentType === "IMPORT_BOARDS" && }
diff --git a/src/server/api/root.ts b/src/server/api/root.ts index a4a9a58c..d71e1cdb 100644 --- a/src/server/api/root.ts +++ b/src/server/api/root.ts @@ -2,6 +2,7 @@ import { boardRouter } from "~/server/api/routers/board"; import { cardRouter } from "~/server/api/routers/card"; import { labelRouter } from "~/server/api/routers/label"; import { listRouter } from "~/server/api/routers/list"; +import { importRouter } from "~/server/api/routers/import"; import { createTRPCRouter } from "~/server/api/trpc"; /** @@ -14,6 +15,7 @@ export const appRouter = createTRPCRouter({ card: cardRouter, label: labelRouter, list: listRouter, + import: importRouter, }); // export type definition of API diff --git a/src/server/api/routers/import.ts b/src/server/api/routers/import.ts new file mode 100644 index 00000000..a647fcea --- /dev/null +++ b/src/server/api/routers/import.ts @@ -0,0 +1,63 @@ +import { z } from "zod"; + +import { + createTRPCRouter, + publicProcedure, +} from "~/server/api/trpc"; + +const TRELLO_API_URL = 'https://api.trello.com/1'; + +interface BoardData { + id: string; + name: string; +} + +interface MemberData { + idBoards: string[]; +} + +export const importRouter = createTRPCRouter({ + trello: createTRPCRouter({ + getBoards: publicProcedure + .input( + z.object({ + apiKey: z.string().length(32), + token: z.string().length(76), + }), + ) + .query(async ({ ctx, input }) => { + const userId = ctx.session?.user.id; + + if (!userId) return; + + console.log({ input }) + + const fetchMemberRes = await fetch(`${TRELLO_API_URL}/tokens/${input.token}/member?key=${input.apiKey}`) + + const member = await fetchMemberRes.json() as MemberData; + + const boardIds = member.idBoards; + + const fetchBoard = async (boardId: string) => { + try { + const response = await fetch(`${TRELLO_API_URL}/boards/${boardId}?key=${input.apiKey}&token=${input.token}`); + const data = await response.json() as BoardData; + + return data; + } catch (error) { + throw error; + } + }; + + const boards = []; + + for (const boardId of boardIds) { + boards.push(Promise.resolve(fetchBoard(boardId))); + } + + const boardDataArray = await Promise.all(boards); + + return boardDataArray.map((board) => ({ id: board.id, name: board.name })); + }), + }) +}); \ No newline at end of file