diff --git a/bun.lockb b/bun.lockb index d647668a..e412d77d 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index b0f3e5aa..2c62c8a8 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "react-icons": "^4.11.0", "react-lottie-player": "^1.5.5", "superjson": "^1.13.1", + "tailwind-merge": "^2.5.2", "zod": "^3.22.4" }, "devDependencies": { diff --git a/src/components/Button.tsx b/src/components/Button.tsx index 280816ae..0c2531fd 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -1,11 +1,25 @@ +import { twMerge } from "tailwind-merge"; + interface ButtonProps extends React.ButtonHTMLAttributes { + variant?: "primary" | "secondary"; isLoading?: boolean; } -const Button = ({ children, isLoading, ...props }: ButtonProps) => { +const Button = ({ + children, + isLoading, + variant = "primary", + ...props +}: ButtonProps) => { return ( - + + ); diff --git a/src/views/board/components/DeleteListConfirmation.tsx b/src/views/board/components/DeleteListConfirmation.tsx index 0ed6e4a8..a89bcde3 100644 --- a/src/views/board/components/DeleteListConfirmation.tsx +++ b/src/views/board/components/DeleteListConfirmation.tsx @@ -2,6 +2,8 @@ import { api } from "~/utils/api"; import { useBoard } from "~/providers/board"; import { useModal } from "~/providers/modal"; +import Button from "~/components/Button"; + interface DeleteListConfirmationProps { listPublicId: string; } @@ -40,23 +42,13 @@ export function DeleteListConfirmation({ {"This action can't be undone."}

-
- - + +
); diff --git a/src/views/board/components/NewCardForm.tsx b/src/views/board/components/NewCardForm.tsx index cae4dc25..e5b11817 100644 --- a/src/views/board/components/NewCardForm.tsx +++ b/src/views/board/components/NewCardForm.tsx @@ -1,22 +1,22 @@ import { useEffect } from "react"; import { useForm } from "react-hook-form"; -import ContentEditable from "react-contenteditable"; -import { api } from "~/utils/api"; - import { HiXMark, HiOutlineBarsArrowDown, HiOutlineBarsArrowUp, } from "react-icons/hi2"; -import { Switch } from "@headlessui/react"; - +import Button from "~/components/Button"; import CheckboxDropdown from "~/components/CheckboxDropdown"; +import Input from "~/components/Input"; +import Toggle from "~/components/Toggle"; import { useBoard } from "~/providers/board"; import { useModal } from "~/providers/modal"; import { usePopup } from "~/providers/popup"; +import { api } from "~/utils/api"; + import { type NewCardInput } from "~/types/router.types"; type NewCardFormInput = NewCardInput & { @@ -27,10 +27,6 @@ interface NewCardFormProps { listPublicId: string; } -function classNames(...classes: string[]): string { - return classes.filter(Boolean).join(" "); -} - export function NewCardForm({ listPublicId }: NewCardFormProps) { const { boardData, addCard, refetchBoard } = useBoard(); const { showPopup } = usePopup(); @@ -168,20 +164,14 @@ export function NewCardForm({ listPublicId }: NewCardFormProps) {
- +
- setValue("description", e.target.value)} - className="block min-h-[70px] w-full rounded-md border-0 bg-dark-300 bg-white/5 px-3 py-1.5 text-light-900 text-neutral-900 shadow-sm ring-1 ring-inset ring-light-600 focus:ring-2 focus:ring-inset focus:ring-light-600 focus-visible:outline-none dark:text-dark-1000 dark:ring-dark-700 dark:focus:ring-dark-700 sm:text-sm sm:leading-6" + value={watch("description")} + contentEditable />
@@ -301,38 +291,14 @@ export function NewCardForm({ listPublicId }: NewCardFormProps) {
-
- - Create more - - - Create another - -
+
- +
diff --git a/src/views/board/components/NewListForm.tsx b/src/views/board/components/NewListForm.tsx index 9792a2e9..310fd701 100644 --- a/src/views/board/components/NewListForm.tsx +++ b/src/views/board/components/NewListForm.tsx @@ -1,19 +1,19 @@ import { useEffect } from "react"; -import { api } from "~/utils/api"; import { useForm } from "react-hook-form"; import { HiXMark } from "react-icons/hi2"; -import { Switch } from "@headlessui/react"; import { useBoard } from "~/providers/board"; import { useModal } from "~/providers/modal"; import { usePopup } from "~/providers/popup"; -import { type NewListInput } from "~/types/router.types"; +import { api } from "~/utils/api"; -function classNames(...classes: string[]): string { - return classes.filter(Boolean).join(" "); -} +import Button from "~/components/Button"; +import Input from "~/components/Input"; +import Toggle from "~/components/Toggle"; + +import { type NewListInput } from "~/types/router.types"; type NewListFormInput = NewListInput & { isCreateAnotherEnabled: boolean; @@ -88,48 +88,19 @@ export function NewListForm({ boardPublicId }: { boardPublicId: string }) { - +
-
- - Create more - - - setValue("isCreateAnotherEnabled", !isCreateAnotherEnabled) - } - className={classNames( - isCreateAnotherEnabled - ? "bg-indigo-600" - : "bg-light-800 dark:bg-dark-800", - "relative inline-flex h-4 w-6 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none", - )} - > - Create another - -
+ + setValue("isCreateAnotherEnabled", !isCreateAnotherEnabled) + } + />
- +
diff --git a/src/views/card/components/NewLabelForm.tsx b/src/views/card/components/NewLabelForm.tsx index 1c3586bc..37cca753 100644 --- a/src/views/card/components/NewLabelForm.tsx +++ b/src/views/card/components/NewLabelForm.tsx @@ -1,23 +1,26 @@ import { Fragment } from "react"; -import { Listbox, Transition } from "@headlessui/react"; -import { api } from "~/utils/api"; import { HiChevronUpDown, HiXMark } from "react-icons/hi2"; -import { useModal } from "~/providers/modal"; import { useForm, Controller } from "react-hook-form"; +import { Listbox, Transition } from "@headlessui/react"; -interface FormValues { - name: string; +import { api } from "~/utils/api"; +import { useModal } from "~/providers/modal"; + +import Button from "~/components/Button"; +import Input from "~/components/Input"; +import Toggle from "~/components/Toggle"; + +import { type NewLabelInput } from "~/types/router.types"; + +type NewLabelFormInput = NewLabelInput & { colour: Colour; -} + isCreateAnotherEnabled: boolean; +}; -interface Colour { +type Colour = { name: string; code: string; -} - -interface CardPublicId { - cardPublicId: string; -} +}; const colours = [ { name: "Teal", code: "#0d9488" }, @@ -30,31 +33,43 @@ const colours = [ { name: "Pink", code: "#db2777" }, ]; -export function NewLabelForm({ cardPublicId }: CardPublicId) { +export function NewLabelForm({ cardPublicId }: { cardPublicId: string }) { const utils = api.useUtils(); const { closeModal } = useModal(); - const { control, handleSubmit } = useForm({ - defaultValues: { - name: "", - colour: colours[0], - }, - }); + const { control, register, reset, handleSubmit, setValue, watch } = + useForm({ + defaultValues: { + name: "", + colour: colours[0], + isCreateAnotherEnabled: false, + }, + }); const refetchCard = () => utils.card.byId.refetch({ id: cardPublicId }); + const isCreateAnotherEnabled = watch("isCreateAnotherEnabled"); + const createLabel = api.label.create.useMutation({ onSuccess: async () => { + const currentColourIndex = colours.findIndex( + (c) => c.code === watch("colour").code, + ); try { await refetchCard(); - closeModal(); + if (!isCreateAnotherEnabled) closeModal(); + reset({ + name: "", + colour: colours[(currentColourIndex + 1) % colours.length], + isCreateAnotherEnabled, + }); } catch (e) { console.log(e); } }, }); - const onSubmit = (values: FormValues) => { + const onSubmit = (values: NewLabelFormInput) => { if (!values.colour?.code) return; createLabel.mutate({ @@ -65,35 +80,22 @@ export function NewLabelForm({ cardPublicId }: CardPublicId) { }; return ( -
-
-

New label

- -
+
+
+
+

New label

+ +
- - - ( - - )} - /> + )} /> -
- +
+ +
+ + setValue("isCreateAnotherEnabled", !isCreateAnotherEnabled) + } + /> + +
+
- -
+
+ ); }