Skip to content

Commit

Permalink
createw new project in add task or task detail page
Browse files Browse the repository at this point in the history
  • Loading branch information
CREDO23 committed Nov 21, 2024
1 parent 681714b commit b914188
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 156 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
ActiveTaskSizesDropdown,
ActiveTaskStatusDropdown,
ActiveTaskVersionDropdown,
CreateTeamModal,
EpicPropertiesDropdown as TaskEpicDropdown,
TaskLabels,
TaskStatus,
Expand All @@ -21,11 +22,12 @@ import { Fragment, useCallback, useEffect, useMemo, useState } from 'react';
import { useAtomValue } from 'jotai';
import TaskRow from '../components/task-row';
import { useTranslations } from 'next-intl';
import { ChevronDownIcon, Square4OutlineIcon } from 'assets/svg';
import { AddIcon, ChevronDownIcon, Square4OutlineIcon, TrashIcon } from 'assets/svg';
import { Listbox, Transition } from '@headlessui/react';
import { clsxm } from '@/app/utils';
import { organizationProjectsState } from '@/app/stores/organization-projects';
import ProjectIcon from '@components/ui/svgs/project-icon';
import { ScrollArea, ScrollBar } from '@components/ui/scroll-bar';

type StatusType = 'version' | 'epic' | 'status' | 'label' | 'size' | 'priority';

Expand Down Expand Up @@ -104,23 +106,6 @@ const TaskSecondaryInfo = () => {
</ActiveTaskVersionDropdown>
</TaskRow>

{/* Epic */}
{task && task.issueType === 'Story' && (
<TaskRow labelTitle={t('pages.taskDetails.EPIC')}>
<TaskEpicDropdown
onValueChange={(d) => {
onTaskSelect({
id: d
} as ITeamTask);
}}
className="lg:min-w-[170px] text-black"
forDetails={true}
sidebarUI={true}
taskStatusClassName="text-[0.625rem] w-[7.6875rem] h-[2.35rem] max-w-[7.6875rem] rounded 3xl:text-xs"
defaultValue={task.parentId || ''}
/>
</TaskRow>
)}
{/* Epic */}
{task && task.issueType === 'Story' && (
<TaskRow labelTitle={t('pages.taskDetails.EPIC')}>
Expand All @@ -139,27 +124,8 @@ const TaskSecondaryInfo = () => {
</TaskRow>
)}

{task && <EpicParent task={task} />}
{task && <EpicParent task={task} />}

{/* Task Status */}
<TaskRow labelTitle={t('pages.taskDetails.STATUS')}>
<ActiveTaskStatusDropdown
task={task}
className="lg:min-w-[170px] text-black"
forDetails={true}
sidebarUI={true}
taskStatusClassName="text-[0.625rem] w-[7.6875rem] h-[2.35rem] max-w-[7.6875rem] rounded 3xl:text-xs"
>
<Button
className="w-full px-2 py-1 text-xs dark:text-white dark:border-white"
variant="outline"
onClick={openModalEditionHandle('status')}
>
<PlusIcon className="w-4 h-4" />
</Button>
</ActiveTaskStatusDropdown>
</TaskRow>
{/* Task Status */}
<TaskRow labelTitle={t('pages.taskDetails.STATUS')}>
<ActiveTaskStatusDropdown
Expand All @@ -179,34 +145,6 @@ const TaskSecondaryInfo = () => {
</ActiveTaskStatusDropdown>
</TaskRow>

{/* Task Labels */}
<TaskRow labelTitle={t('pages.taskDetails.LABELS')}>
<TaskLabels
task={task}
className="lg:min-w-[170px] text-black lg:mt-0"
forDetails={true}
taskStatusClassName="text-[0.625rem] w-[7.6875rem] h-[2.35rem] max-w-[7.6875rem] rounded 3xl:text-xs"
/>
</TaskRow>
{tags.length > 0 && (
<TaskRow>
<div className="flex flex-row flex-wrap gap-1 max-w-[10rem]">
{tags.map((tag, i) => {
return (
<Tooltip key={i} label={tag.name?.split('-').join(' ') || ''} placement="auto">
<TaskStatus
{...tag}
className="rounded-[0.625rem] h-6 max-w-[8rem]"
active={true}
name={tag.name?.split('-').join(' ')}
titleClassName={'text-[0.625rem] font-[500]'}
/>
</Tooltip>
);
})}
</div>
</TaskRow>
)}
{/* Task Labels */}
<TaskRow labelTitle={t('pages.taskDetails.LABELS')}>
<TaskLabels
Expand Down Expand Up @@ -277,7 +215,7 @@ const TaskSecondaryInfo = () => {
{/* Task project */}
{task && (
<TaskRow labelTitle={t('pages.taskDetails.PROJECT')} wrapperClassName="text-black">
<ProjectDropDown task={task} />
<ProjectDropDown styles={{ listCard: 'rounded-xl' }} task={task} />
</TaskRow>
)}
<Modal isOpen={modal.isOpen} closeModal={modal.closeModal}>
Expand Down Expand Up @@ -344,7 +282,7 @@ export default TaskSecondaryInfo;
*/
export function ProjectDropDown(props: ITaskProjectDropdownProps) {
const { task, controlled = false, onChange, styles } = props;

const { openModal, isOpen, closeModal } = useModal();
const organizationProjects = useAtomValue(organizationProjectsState);
const { getOrganizationProjects } = useOrganizationProjects();
const { updateTask, updateLoading } = useTeamTasks();
Expand Down Expand Up @@ -395,96 +333,115 @@ export function ProjectDropDown(props: ITaskProjectDropdownProps) {
}, [task, updateTask]);

return (
<div
className={clsxm(
'relative text-sm font-medium border text-[0.625rem] w-[7.6875rem] h-[2.35rem] max-w-[7.6875rem] rounded 3xl:text-xs',
styles?.container
)}
>
<Listbox
value={selected}
onChange={(project) => {
if (controlled && onChange) {
onChange(project);
} else {
handleUpdateProject(project);
}

setSelected(project);
}}
<>
<div
className={clsxm(
'relative text-sm font-medium border text-[0.625rem] w-[7.6875rem] h-[2.35rem] max-w-[7.6875rem] rounded 3xl:text-xs',
styles?.container
)}
>
{({ open }) => {
return (
<>
<Listbox.Button
className={clsxm(
'cursor-pointer outline-none w-full flex items-center justify-between px-4 h-full ',
styles?.value
)}
>
{selected && (
<div className="">
<ProjectIcon />
</div>
)}
{updateLoading ? (
<SpinnerLoader size={10} />
) : (
<p className={clsxm('truncate', !selected && ' text-slate-400 font-light')}>
{selected?.name ?? 'Project'}
</p>
)}
<ChevronDownIcon
<Listbox
value={selected}
onChange={(project) => {
if (controlled && onChange) {
onChange(project);
} else {
handleUpdateProject(project);
}

setSelected(project);
}}
>
{({ open }) => {
return (
<>
<Listbox.Button
className={clsxm(
'h-4 w-4 text-default transition duration-150 ease-in-out group-hover:text-opacity-80'
'cursor-pointer outline-none w-full flex items-center justify-between px-4 h-full ',
styles?.value
)}
aria-hidden="true"
/>
</Listbox.Button>

<Transition
show={open}
enter="transition duration-100 ease-out"
enterFrom="transform scale-95 opacity-0"
enterTo="transform scale-100 opacity-100"
leave="transition duration-75 ease-out"
leaveFrom="transform scale-100 opacity-100"
leaveTo="transform scale-95 opacity-0"
className={clsxm('absolute right-0 left-0 top-10 z-40 min-w-min outline-none')}
>
<Listbox.Options className="outline-none">
<Card
shadow="bigger"
>
{selected && (
<div className="">
<ProjectIcon />
</div>
)}
{updateLoading ? (
<SpinnerLoader size={10} />
) : (
<p className={clsxm('truncate', !selected && ' text-slate-400 font-light')}>
{selected?.name ?? 'Project'}
</p>
)}
<ChevronDownIcon
className={clsxm(
'p-4 md:p-4 shadow-xlcard dark:shadow-lgcard-white dark:bg-[#1B1D22] dark:border dark:border-[#FFFFFF33] flex flex-col gap-2.5 max-h-[206px] overflow-x-auto rounded-none',
styles?.listCard
'h-4 w-4 text-default transition duration-150 ease-in-out group-hover:text-opacity-80'
)}
>
{organizationProjects.map((item, i) => {
return (
<Listbox.Option key={item.id} value={item} as={Fragment}>
<li className="relative outline-none cursor-pointer">
{item.name}
</li>
</Listbox.Option>
);
})}
{!controlled && (
<Button
className=" px-2 py-1 mt-2 !min-w-min rounded-none text-xs dark:text-white dark:border-white"
variant="outline"
onClick={handleRemoveProject}
>
{t('common.REMOVE')}
</Button>
)}
</Card>
</Listbox.Options>
</Transition>
</>
);
}}
</Listbox>
</div>
aria-hidden="true"
/>
</Listbox.Button>

<Transition
show={open}
enter="transition duration-100 ease-out"
enterFrom="transform scale-95 opacity-0"
enterTo="transform scale-100 opacity-100"
leave="transition duration-75 ease-out"
leaveFrom="transform scale-100 opacity-100"
leaveTo="transform scale-95 opacity-0"
className={clsxm('absolute right-0 left-0 top-10 z-40 min-w-min outline-none')}
>
<Listbox.Options className="outline-none">
<Card
shadow="bigger"
className={clsxm(
'p-0 md:p-0 shadow-xlcard dark:shadow-lgcard-white dark:bg-[#1B1D22] dark:border dark:border-[#FFFFFF33] flex flex-col gap-2.5 h-[13rem] max-h-[13rem] overflow-x-auto rounded-none overflow-hidden',
styles?.listCard
)}
>
<ScrollArea className="w-full h-full">
<div className="flex flex-col gap-2.5 w-full p-4">
{organizationProjects.map((item, i) => {
return (
<Listbox.Option key={item.id} value={item} as={Fragment}>
<li className="relative border h-[2rem] flex items-center gap-1 px-2 rounded-lg outline-none cursor-pointer">
<ProjectIcon width={14} height={14} />{' '}
<span className=" truncate">{item.name}</span>
</li>
</Listbox.Option>
);
})}
{!controlled && (
<div className="mt-2">
<Button
className=" px-2 py-1 w-full !justify-start !gap-2 !min-w-min h-[2rem] rounded-lg text-xs dark:text-white dark:border-white"
variant="outline"
onClick={handleRemoveProject}
>
<TrashIcon className="w-5 " /> {t('common.REMOVE')}
</Button>
<Button
className=" px-2 py-1 mt-2 w-full !justify-start !min-w-min h-[2rem] rounded-lg text-xs dark:text-white dark:border-white"
variant="outline"
onClick={openModal}
>
<AddIcon className="w-3 h-3 text-dark dark:text-white" />{' '}
<span className=" truncate">Create new</span>
</Button>
</div>
)}
</div>
<ScrollBar className="-pr-60" />
</ScrollArea>
</Card>
</Listbox.Options>
</Transition>
</>
);
}}
</Listbox>
</div>
{<CreateTeamModal open={isOpen} closeModal={closeModal} />}
</>
);
}
12 changes: 10 additions & 2 deletions apps/web/components/ui/svgs/project-icon.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
export default function ProjectIcon() {
import { IIconProps } from '@/app/interfaces';

export default function ProjectIcon(props: Partial<IIconProps>) {
return (
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<svg
width={props.width ?? 18}
height={props.height ?? 18}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 12.2501C11.56 12.2501 11.12 12.1401 10.72 11.9301L4.21 8.4201C3.62 8.1001 3.25 7.4701 3.25 6.7701C3.25 6.0701 3.62 5.4401 4.21 5.1201L10.72 1.6101C11.52 1.1801 12.48 1.1801 13.27 1.6101L19.78 5.1201C20.37 5.4401 20.74 6.0701 20.74 6.7701C20.74 7.4701 20.37 8.1001 19.78 8.4201L13.27 11.9301C12.88 12.1501 12.44 12.2501 12 12.2501ZM12 2.7801C11.81 2.7801 11.61 2.8301 11.43 2.9301L4.93 6.4301C4.76 6.5201 4.75 6.7101 4.75 6.7701C4.75 6.8301 4.76 7.0201 4.93 7.1001L11.44 10.6101C11.8 10.8001 12.21 10.8001 12.57 10.6101L19.08 7.1001C19.24 7.0101 19.26 6.8201 19.26 6.7701C19.26 6.7101 19.25 6.5201 19.08 6.4401L12.57 2.9301C12.39 2.8301 12.19 2.7801 12 2.7801Z"
fill="#292D32"
Expand Down
2 changes: 1 addition & 1 deletion apps/web/lib/features/task/task-status.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1079,7 +1079,7 @@ export function StatusDropdown<T extends TStatusItem>({
<Listbox.Options className="outline-none">
<Card
shadow="bigger"
className="p-4 md:p-4 shadow-xlcard dark:shadow-lgcard-white dark:bg-[#1B1D22] dark:border dark:border-[#FFFFFF33] flex flex-col gap-2.5 max-h-[206px] overflow-x-auto"
className="p-4 md:p-4 shadow-xlcard dark:shadow-lgcard-white dark:bg-[#1B1D22] dark:border dark:border-[#FFFFFF33] flex flex-col gap-2.5 overflow-x-auto"
>
{items.map((item, i) => {
const item_value = item?.value || item?.name;
Expand Down

0 comments on commit b914188

Please sign in to comment.