diff --git a/apps/app/components/issues/select/assignee.tsx b/apps/app/components/issues/select/assignee.tsx index 8aaf4cb40..1c2df619f 100644 --- a/apps/app/components/issues/select/assignee.tsx +++ b/apps/app/components/issues/select/assignee.tsx @@ -1,18 +1,17 @@ import { useState, FC, Fragment } from "react"; -import Image from "next/image"; import { useRouter } from "next/router"; import useSWR from "swr"; // headless ui import { Transition, Combobox } from "@headlessui/react"; +// services +import projectServices from "services/project.service"; +// ui +import { Avatar } from "components/ui"; // icons import { UserIcon } from "@heroicons/react/24/outline"; -// service -import projectServices from "services/project.service"; -// types -import type { IProjectMember } from "types"; // fetch keys import { PROJECT_MEMBERS } from "constants/fetch-keys"; @@ -22,35 +21,6 @@ export type IssueAssigneeSelectProps = { onChange: (value: string[]) => void; }; -type AssigneeAvatarProps = { - user: IProjectMember | undefined; -}; - -export const AssigneeAvatar: FC = ({ user }) => { - if (!user) return <>; - - if (user.member.avatar && user.member.avatar !== "") { - return ( -
- avatar -
- ); - } else - return ( -
- {user.member.first_name && user.member.first_name !== "" - ? user.member.first_name.charAt(0) - : user.member.email.charAt(0)} -
- ); -}; - export const IssueAssigneeSelect: FC = ({ projectId, value = [], @@ -136,14 +106,14 @@ export const IssueAssigneeSelect: FC = ({ className={({ active, selected }) => `${active ? "bg-indigo-50" : ""} ${ selected ? "bg-indigo-50 font-medium" : "" - } flex cursor-pointer select-none items-center gap-2 truncate p-2 text-gray-900` + } flex cursor-pointer select-none items-center gap-2 truncate px-2 py-1 text-gray-900` } value={option.value} > {people && ( <> - p.member.id === option.value)} + p.member.id === option.value)?.member} /> {option.display} diff --git a/apps/app/components/issues/sidebar-select/assignee.tsx b/apps/app/components/issues/sidebar-select/assignee.tsx index 369d03368..865e7fffd 100644 --- a/apps/app/components/issues/sidebar-select/assignee.tsx +++ b/apps/app/components/issues/sidebar-select/assignee.tsx @@ -97,8 +97,8 @@ export const SidebarAssigneeSelect: React.FC = ({ control, submitChanges, - `${ - active || selected ? "bg-indigo-50" : "" + `${active || selected ? "bg-indigo-50" : ""} ${ + selected ? "font-medium" : "" } flex cursor-pointer select-none items-center gap-2 truncate p-2 text-gray-900` } value={option.member.id} diff --git a/apps/app/components/issues/view-select/priority.tsx b/apps/app/components/issues/view-select/priority.tsx index 9f55937a2..096d6e93f 100644 --- a/apps/app/components/issues/view-select/priority.tsx +++ b/apps/app/components/issues/view-select/priority.tsx @@ -1,7 +1,7 @@ import React from "react"; // ui -import { Listbox, Transition } from "@headlessui/react"; +import { CustomSelect } from "components/ui"; // icons import { getPriorityIcon } from "components/icons/priority-icon"; // types @@ -22,67 +22,43 @@ export const ViewPrioritySelect: React.FC = ({ position = "right", isNotAllowed, }) => ( - + {getPriorityIcon( + issue.priority && issue.priority !== "" ? issue.priority ?? "" : "None", + "text-sm" + )} + + } + value={issue.state} onChange={(data: string) => { partialUpdateIssue({ priority: data }); }} - className="group relative flex-shrink-0" + maxHeight="md" + buttonClassName={`flex ${ + isNotAllowed ? "cursor-not-allowed" : "cursor-pointer" + } items-center gap-x-2 rounded px-2 py-0.5 capitalize shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 ${ + issue.priority === "urgent" + ? "bg-red-100 text-red-600 hover:bg-red-100" + : issue.priority === "high" + ? "bg-orange-100 text-orange-500 hover:bg-orange-100" + : issue.priority === "medium" + ? "bg-yellow-100 text-yellow-500 hover:bg-yellow-100" + : issue.priority === "low" + ? "bg-green-100 text-green-500 hover:bg-green-100" + : "bg-gray-100" + } border-none`} + noChevron disabled={isNotAllowed} > - {({ open }) => ( -
- - {getPriorityIcon( - issue.priority && issue.priority !== "" ? issue.priority ?? "" : "None", - "text-sm" - )} - - - - - {PRIORITIES?.map((priority) => ( - - `${active || selected ? "bg-indigo-50" : ""} ${ - selected ? "font-medium" : "" - } flex cursor-pointer select-none items-center gap-x-2 px-3 py-2 capitalize` - } - value={priority} - > - {getPriorityIcon(priority, "text-sm")} - {priority ?? "None"} - - ))} - - -
- )} -
+ {PRIORITIES?.map((priority) => ( + + <> + {getPriorityIcon(priority, "text-sm")} + {priority ?? "None"} + + + ))} + ); diff --git a/apps/app/components/issues/view-select/state.tsx b/apps/app/components/issues/view-select/state.tsx index 67b5cd9b9..b6bac7a0b 100644 --- a/apps/app/components/issues/view-select/state.tsx +++ b/apps/app/components/issues/view-select/state.tsx @@ -24,7 +24,7 @@ type Props = { export const ViewStateSelect: React.FC = ({ issue, partialUpdateIssue, - position, + position = "right", isNotAllowed, }) => { const router = useRouter(); diff --git a/apps/app/components/onboarding/invite-members.tsx b/apps/app/components/onboarding/invite-members.tsx index efcdd650c..e6fc54e37 100644 --- a/apps/app/components/onboarding/invite-members.tsx +++ b/apps/app/components/onboarding/invite-members.tsx @@ -4,8 +4,7 @@ import useToast from "hooks/use-toast"; import workspaceService from "services/workspace.service"; import { IUser } from "types"; // ui components -import MultiInput from "components/ui/multi-input"; -import OutlineButton from "components/ui/outline-button"; +import { MultiInput, OutlineButton } from "components/ui"; type Props = { setStep: React.Dispatch>; diff --git a/apps/app/components/ui/button/index.tsx b/apps/app/components/ui/button.tsx similarity index 100% rename from apps/app/components/ui/button/index.tsx rename to apps/app/components/ui/button.tsx diff --git a/apps/app/components/ui/custom-listbox/index.tsx b/apps/app/components/ui/custom-listbox.tsx similarity index 92% rename from apps/app/components/ui/custom-listbox/index.tsx rename to apps/app/components/ui/custom-listbox.tsx index ff7ed78fe..3a5c2322c 100644 --- a/apps/app/components/ui/custom-listbox/index.tsx +++ b/apps/app/components/ui/custom-listbox.tsx @@ -2,8 +2,19 @@ import React from "react"; // headless ui import { Listbox, Transition } from "@headlessui/react"; -// types -import { Props } from "./types"; + +type Props = { + title?: string; + label?: string; + options?: Array<{ display: string; value: any; color?: string; icon?: JSX.Element }>; + icon?: JSX.Element; + value: any; + onChange: (value: any) => void; + multiple?: boolean; + optionsFontsize?: "sm" | "md" | "lg" | "xl" | "2xl"; + className?: string; + footerOption?: JSX.Element; +}; export const CustomListbox: React.FC = ({ title = "", diff --git a/apps/app/components/ui/custom-listbox/types.d.ts b/apps/app/components/ui/custom-listbox/types.d.ts deleted file mode 100644 index d961f9105..000000000 --- a/apps/app/components/ui/custom-listbox/types.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -export type Props = { - title?: string; - label?: string; - options?: Array<{ display: string; value: any; color?: string; icon?: JSX.Element }>; - icon?: JSX.Element; - value: any; - onChange: (value: any) => void; - multiple?: boolean; - optionsFontsize?: "sm" | "md" | "lg" | "xl" | "2xl"; - className?: string; - footerOption?: JSX.Element; -}; diff --git a/apps/app/components/ui/custom-menu/index.tsx b/apps/app/components/ui/custom-menu.tsx similarity index 88% rename from apps/app/components/ui/custom-menu/index.tsx rename to apps/app/components/ui/custom-menu.tsx index adf31942d..e34390eff 100644 --- a/apps/app/components/ui/custom-menu/index.tsx +++ b/apps/app/components/ui/custom-menu.tsx @@ -5,9 +5,25 @@ import Link from "next/link"; import { Menu, Transition } from "@headlessui/react"; // icons import { ChevronDownIcon, EllipsisHorizontalIcon } from "@heroicons/react/24/outline"; -// types -import { MenuItemProps, Props } from "./types"; -// constants + +type Props = { + children: React.ReactNode; + label?: string | JSX.Element; + className?: string; + ellipsis?: boolean; + width?: "sm" | "md" | "lg" | "xl" | "auto"; + textAlignment?: "left" | "center" | "right"; + noBorder?: boolean; + optionsPosition?: "left" | "right"; +}; + +type MenuItemProps = { + children: JSX.Element | string; + renderAs?: "button" | "a"; + href?: string; + onClick?: () => void; + className?: string; +}; const CustomMenu = ({ children, diff --git a/apps/app/components/ui/custom-menu/types.d.ts b/apps/app/components/ui/custom-menu/types.d.ts deleted file mode 100644 index 588b30ab0..000000000 --- a/apps/app/components/ui/custom-menu/types.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -export type Props = { - children: React.ReactNode; - label?: string | JSX.Element; - className?: string; - ellipsis?: boolean; - width?: "sm" | "md" | "lg" | "xl" | "auto"; - textAlignment?: "left" | "center" | "right"; - noBorder?: boolean; - optionsPosition?: "left" | "right"; -}; - -export type MenuItemProps = { - children: JSX.Element | string; - renderAs?: "button" | "a"; - href?: string; - onClick?: () => void; - className?: string; -}; diff --git a/apps/app/components/ui/custom-select/index.tsx b/apps/app/components/ui/custom-select.tsx similarity index 93% rename from apps/app/components/ui/custom-select/index.tsx rename to apps/app/components/ui/custom-select.tsx index e3061bf68..a7d9df3d5 100644 --- a/apps/app/components/ui/custom-select/index.tsx +++ b/apps/app/components/ui/custom-select.tsx @@ -14,6 +14,7 @@ type CustomSelectProps = { width?: "auto" | string; input?: boolean; noChevron?: boolean; + buttonClassName?: string; disabled?: boolean; }; @@ -27,6 +28,7 @@ const CustomSelect = ({ width = "auto", input = false, noChevron = false, + buttonClassName = "", disabled = false, }: CustomSelectProps) => (
= ({ children, value, className }) => ( - `${selected ? "bg-indigo-50 font-medium" : ""} ${ - active ? "bg-indigo-50" : "" + `${active || selected ? "bg-indigo-50" : ""} ${ + selected ? "font-medium" : "" } relative flex cursor-pointer select-none items-center gap-2 truncate p-2 text-gray-900 ${className}` } > diff --git a/apps/app/components/ui/empty-space/index.tsx b/apps/app/components/ui/empty-space.tsx similarity index 100% rename from apps/app/components/ui/empty-space/index.tsx rename to apps/app/components/ui/empty-space.tsx diff --git a/apps/app/components/ui/header-button/index.tsx b/apps/app/components/ui/header-button.tsx similarity index 100% rename from apps/app/components/ui/header-button/index.tsx rename to apps/app/components/ui/header-button.tsx diff --git a/apps/app/components/ui/index.ts b/apps/app/components/ui/index.ts index 8311c0237..04cb34fa3 100644 --- a/apps/app/components/ui/index.ts +++ b/apps/app/components/ui/index.ts @@ -1,15 +1,17 @@ +export * from "./input"; +export * from "./text-area"; +export * from "./avatar"; export * from "./button"; export * from "./custom-listbox"; export * from "./custom-menu"; export * from "./custom-select"; +export * from "./datepicker"; export * from "./empty-space"; export * from "./header-button"; -export * from "./input"; export * from "./loader"; +export * from "./multi-input"; export * from "./outline-button"; +export * from "./progress-bar"; export * from "./select"; export * from "./spinner"; -export * from "./text-area"; -export * from "./avatar"; -export * from "./datepicker"; export * from "./tooltip"; diff --git a/apps/app/components/ui/loader/index.tsx b/apps/app/components/ui/loader.tsx similarity index 100% rename from apps/app/components/ui/loader/index.tsx rename to apps/app/components/ui/loader.tsx diff --git a/apps/app/components/ui/modal/index.tsx b/apps/app/components/ui/modal/index.tsx deleted file mode 100644 index 10de152b1..000000000 --- a/apps/app/components/ui/modal/index.tsx +++ /dev/null @@ -1,116 +0,0 @@ -import { Fragment, ReactNode } from "react"; -// Headless ui imports -import { Dialog, Transition } from "@headlessui/react"; -// Design components -import { XMarkIcon } from "@heroicons/react/24/outline"; -import { Button } from "components/ui"; -// Icons - -type ModalProps = { - isModal: boolean; - setModal: Function; - size?: "xs" | "rg" | "lg" | "xl"; - position?: "top" | "center" | "bottom"; - title: string; - children: ReactNode; - buttons?: ReactNode; - onClose?: Function; - closeButton?: string; - continueButton?: string; -}; - -const Modal = (props: ModalProps) => { - const closeModal = () => { - props.setModal(false); - props.onClose ? props.onClose() : () => ({}); - }; - - const width: string = - props.size === "xs" - ? "w-4/12" - : props.size === "rg" - ? "w-6/12" - : props.size === "lg" - ? "w-9/12" - : props.size === "xl" - ? "w-full" - : "w-auto"; - - const position: string = - props.position === "top" - ? "content-start justify-items-center" - : props.position === "center" - ? "place-items-center" - : props.position === "bottom" - ? "content-end justify-items-center" - : "place-items-center"; - - return ( - <> - - - -
- - -
-
- - - -
- -
-
{props.title}
-
-
{props.children}
-
-
- - -
-
-
-
-
-
-
-
- - ); -}; - -Modal.defaultProps = { - size: "rg", - position: "center", - closeButton: "Close", - continueButton: "Continue", -}; - -export default Modal; diff --git a/apps/app/components/ui/multi-input/index.tsx b/apps/app/components/ui/multi-input.tsx similarity index 95% rename from apps/app/components/ui/multi-input/index.tsx rename to apps/app/components/ui/multi-input.tsx index b26d2b60d..7f2697bf3 100644 --- a/apps/app/components/ui/multi-input/index.tsx +++ b/apps/app/components/ui/multi-input.tsx @@ -8,7 +8,7 @@ const isEmailValid = (email: string) => /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ ); -const MultiInput = ({ label, name, placeholder, setValue, watch }: any) => { +export const MultiInput = ({ label, name, placeholder, setValue, watch }: any) => { const handleKeyDown = (e: any) => { if (e.key !== "Enter") return; const value = e.target.value; @@ -72,5 +72,3 @@ const MultiInput = ({ label, name, placeholder, setValue, watch }: any) => { ); }; - -export default MultiInput; diff --git a/apps/app/components/ui/outline-button/index.tsx b/apps/app/components/ui/outline-button.tsx similarity index 94% rename from apps/app/components/ui/outline-button/index.tsx rename to apps/app/components/ui/outline-button.tsx index b1f8e23d3..5f67fb0f6 100644 --- a/apps/app/components/ui/outline-button/index.tsx +++ b/apps/app/components/ui/outline-button.tsx @@ -10,7 +10,7 @@ type Props = { disabled?: boolean; }; -const OutlineButton = React.forwardRef( +export const OutlineButton = React.forwardRef( ( { children, @@ -58,5 +58,3 @@ const OutlineButton = React.forwardRef( ); OutlineButton.displayName = "Button"; - -export default OutlineButton; diff --git a/apps/app/components/ui/progress-bar/index.tsx b/apps/app/components/ui/progress-bar.tsx similarity index 96% rename from apps/app/components/ui/progress-bar/index.tsx rename to apps/app/components/ui/progress-bar.tsx index 0bebcb93c..4bdfe73f0 100644 --- a/apps/app/components/ui/progress-bar/index.tsx +++ b/apps/app/components/ui/progress-bar.tsx @@ -9,7 +9,7 @@ type Props = { inactiveStrokeColor?: string; }; -const ProgressBar: React.FC = ({ +export const ProgressBar: React.FC = ({ maxValue = 0, value = 0, radius = 8, @@ -67,4 +67,3 @@ const ProgressBar: React.FC = ({ ); }; -export default ProgressBar; diff --git a/apps/app/components/ui/select.tsx b/apps/app/components/ui/select.tsx new file mode 100644 index 000000000..249601ab7 --- /dev/null +++ b/apps/app/components/ui/select.tsx @@ -0,0 +1,60 @@ +import React from "react"; + +// react-hook-form +import { RegisterOptions, UseFormRegister } from "react-hook-form"; + +type Props = { + label?: string; + id: string; + name: string; + value?: string | number | readonly string[]; + className?: string; + register?: UseFormRegister; + disabled?: boolean; + validations?: RegisterOptions; + error?: any; + autoComplete?: "on" | "off"; + options: { label: string; value: any }[]; + size?: "rg" | "lg"; + fullWidth?: boolean; +}; + +export const Select: React.FC = ({ + id, + label, + value, + className = "", + name, + register, + disabled, + validations, + error, + options, + size = "rg", + fullWidth = true, +}) => ( + <> + {label && ( + + )} + + {error?.message &&
{error.message}
} + +); diff --git a/apps/app/components/ui/select/index.tsx b/apps/app/components/ui/select/index.tsx deleted file mode 100644 index e2c3ad5f2..000000000 --- a/apps/app/components/ui/select/index.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import React from "react"; -// types -import { Props } from "./types"; - -export const Select: React.FC = ({ - id, - label, - value, - className = "", - name, - register, - disabled, - validations, - error, - options, - size = "rg", - fullWidth = true, -}) => ( - <> - {label && ( - - )} - - {error?.message && ( -
{error.message}
- )} - - ); diff --git a/apps/app/components/ui/select/types.d.ts b/apps/app/components/ui/select/types.d.ts deleted file mode 100644 index dd50d387c..000000000 --- a/apps/app/components/ui/select/types.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { UseFormRegister, RegisterOptions } from "react-hook-form"; - -export type Props = { - label?: string; - id: string; - name: string; - value?: string | number | readonly string[]; - className?: string; - register?: UseFormRegister; - disabled?: boolean; - validations?: RegisterOptions; - error?: any; - autoComplete?: "on" | "off"; - options: { label: string; value: any }[]; - size?: "rg" | "lg"; - fullWidth?: boolean; -}; diff --git a/apps/app/components/ui/spinner/index.tsx b/apps/app/components/ui/spinner.tsx similarity index 100% rename from apps/app/components/ui/spinner/index.tsx rename to apps/app/components/ui/spinner.tsx diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx index e85000f11..435d3eb38 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx @@ -20,9 +20,8 @@ import EmojiIconPicker from "components/emoji-icon-picker"; // hooks import useToast from "hooks/use-toast"; // ui -import { Button, Input, TextArea, Loader, CustomSelect } from "components/ui"; +import { Button, Input, TextArea, Loader, CustomSelect, OutlineButton } from "components/ui"; import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; -import OutlineButton from "components/ui/outline-button"; // helpers import { debounce } from "helpers/common.helper"; // types diff --git a/apps/app/pages/[workspaceSlug]/settings/index.tsx b/apps/app/pages/[workspaceSlug]/settings/index.tsx index 5ee704bce..0a690592f 100644 --- a/apps/app/pages/[workspaceSlug]/settings/index.tsx +++ b/apps/app/pages/[workspaceSlug]/settings/index.tsx @@ -24,9 +24,8 @@ import useToast from "hooks/use-toast"; import { ImageUploadModal } from "components/core"; import ConfirmWorkspaceDeletion from "components/workspace/confirm-workspace-deletion"; // ui -import { Spinner, Button, Input, CustomSelect } from "components/ui"; +import { Spinner, Button, Input, CustomSelect, OutlineButton } from "components/ui"; import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; -import OutlineButton from "components/ui/outline-button"; // helpers import { copyTextToClipboard } from "helpers/string.helper"; // types