diff --git a/apps/mobile/yarn.lock b/apps/mobile/yarn.lock
index 3963b6634..196734dc3 100644
--- a/apps/mobile/yarn.lock
+++ b/apps/mobile/yarn.lock
@@ -4014,11 +4014,11 @@ axios@^0.27.2:
form-data "^4.0.0"
axios@^1.6.0:
- version "1.6.2"
- resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.2.tgz#de67d42c755b571d3e698df1b6504cde9b0ee9f2"
- integrity sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==
+ version "1.6.8"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.8.tgz#66d294951f5d988a00e87a0ffb955316a619ea66"
+ integrity sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==
dependencies:
- follow-redirects "^1.15.0"
+ follow-redirects "^1.15.6"
form-data "^4.0.0"
proxy-from-env "^1.1.0"
@@ -7162,7 +7162,7 @@ flush-write-stream@^1.0.0:
inherits "^2.0.3"
readable-stream "^2.3.6"
-follow-redirects@^1.0.0, follow-redirects@^1.14.9, follow-redirects@^1.15.0, follow-redirects@^1.4.1:
+follow-redirects@^1.0.0, follow-redirects@^1.14.9, follow-redirects@^1.15.6, follow-redirects@^1.4.1:
version "1.15.6"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==
diff --git a/apps/web/app/[locale]/auth/passcode/component.tsx b/apps/web/app/[locale]/auth/passcode/component.tsx
index 4887069ae..cd861d5ac 100644
--- a/apps/web/app/[locale]/auth/passcode/component.tsx
+++ b/apps/web/app/[locale]/auth/passcode/component.tsx
@@ -13,6 +13,7 @@ import { useRouter } from 'next/navigation';
import { Dispatch, FormEvent, FormEventHandler, SetStateAction, useCallback, useEffect, useRef, useState } from 'react';
import stc from 'string-to-color';
+import { ScrollArea, ScrollBar } from '@components/ui/scroll-bar';
function AuthPasscode() {
const form = useAuthenticationPasscode();
@@ -173,8 +174,8 @@ function PasscodeScreen({ form, className }: { form: TAuthenticationPasscode } &
form.errors['code'] || form.errors['email']
? 'error'
: form.authenticated
- ? 'success'
- : undefined
+ ? 'success'
+ : undefined
}
autoFocus={form.authScreen.screen === 'passcode'}
/>
@@ -317,83 +318,84 @@ export function WorkSpaceComponent(props: IWorkSpace) {
{t('pages.auth.SELECT_WORKSPACE')}
-
-
- {props.workspaces?.map((worksace, index) => (
-
-
-
- {worksace.user.tenant.name}
- {
- props.setSelectedWorkspace(index);
- if (
- props.selectedTeam &&
- !worksace.current_teams
- ?.map((team) => team.team_id)
- .includes(props.selectedTeam)
- ) {
- props.setSelectedTeam(worksace.current_teams[0].team_id);
- }
- }}
- >
- {props.selectedWorkspace === index ? (
-
- ) : (
-
- )}
-
-
-
- {/*
*/}
-
- {worksace.current_teams?.map((team) => (
-
+
+ {props.workspaces?.map((worksace, index) => (
+
+
+
+
{worksace.user.tenant.name}
+
{
+ props.setSelectedWorkspace(index);
+ if (
+ props.selectedTeam &&
+ !worksace.current_teams
+ ?.map((team) => team.team_id)
+ .includes(props.selectedTeam)
+ ) {
+ props.setSelectedTeam(worksace.current_teams[0].team_id);
+ }
+ }}
>
-
-
-
-
- {team.team_name}
-
- ({team.team_member_count})
-
-
- {
- props.setSelectedTeam(team.team_id);
- if (props.selectedWorkspace !== index) {
- props.setSelectedWorkspace(index);
- }
- }}
+ {props.selectedWorkspace === index ? (
+
+ ) : (
+
+ )}
+
+
+
+ {/*
*/}
+
+ {worksace.current_teams?.map((team) => (
+
- {props.selectedTeam === team.team_id ? (
-
- ) : (
-
- )}
-
-
- ))}
+
+
+
+
+ {team.team_name}
+
+ ({team.team_member_count})
+
+
+
{
+ props.setSelectedTeam(team.team_id);
+ if (props.selectedWorkspace !== index) {
+ props.setSelectedWorkspace(index);
+ }
+ }}
+ >
+ {props.selectedTeam === team.team_id ? (
+
+ ) : (
+
+ )}
+
+
+ ))}
+
-
- ))}
-
-
+ ))}
+
+
+
diff --git a/apps/web/app/[locale]/kanban/page.tsx b/apps/web/app/[locale]/kanban/page.tsx
index 7aa669af1..bf5b3fea2 100644
--- a/apps/web/app/[locale]/kanban/page.tsx
+++ b/apps/web/app/[locale]/kanban/page.tsx
@@ -32,6 +32,7 @@ import { useRecoilValue } from 'recoil';
import { fullWidthState } from '@app/stores/fullWidth';
import { CircleIcon } from 'lucide-react';
import { XMarkIcon } from '@heroicons/react/20/solid';
+import Head from 'next/head';
const Kanban = () => {
const {
@@ -85,6 +86,11 @@ const Kanban = () => {
});
return (
<>
+
+
+ {t('common.KANBAN')} {t('common.BOARD')}
+
+
{
if (!locales.includes(locale as any)) notFound();
const router = useRouter();
const pathname = usePathname();
+ const searchParams = useSearchParams();
const { isApiWork, loading } = useCheckAPI();
// Enable static rendering
// unstable_setRequestLocale(locale);
+ const formatTitle = (url: string) => {
+ // Separate the URL into pathname and query parts
+ const [pathname, queryString] = url.split('?');
+
+ // Ignore language codes or any initial two-letter or specific codes like 'ru', 'ur'
+ const segments = pathname
+ .split('/')
+ .filter((seg) => seg && seg.length > 2)
+ .map((seg) => {
+ // Replace dashes with spaces in the segment if it looks like a UUID or has digits (likely an ID)
+ if (seg.includes('-') || /\d/.test(seg)) {
+ return ''; // Exclude IDs from title
+ }
+ return seg.charAt(0).toUpperCase() + seg.slice(1).toLowerCase(); // Capitalize non-ID segments
+ })
+ .filter((seg: string) => seg); // Remove empty strings resulting from ID exclusion
+
+ // Process query parameters, specifically looking for 'name'
+ let namePart = '';
+ if (queryString) {
+ const params = new URLSearchParams(queryString);
+ if (params?.get('name')) {
+ const name = params.get('name') ?? '';
+ const nameValue = name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
+ namePart = nameValue;
+ }
+ }
+
+ // Combine the pathname segments with the name part, if present
+ const title = [...segments, namePart].filter((part) => part).join(' | ');
+
+ return title;
+ };
+
+ const name = searchParams?.get('name');
// eslint-disable-next-line @typescript-eslint/no-var-requires
const messages = require(`../../messages/${locale}.json`);
@@ -69,6 +104,9 @@ const LocaleLayout = ({ children, params: { locale }, pageProps }: Props) => {
}, [isApiWork, loading, router, pathname]);
return (
+
+ {formatTitle(`${pathname}${name ? `?name=${name}` : ''}`) || 'Home'}
+
{/*
diff --git a/apps/web/app/[locale]/profile/[memberId]/page.tsx b/apps/web/app/[locale]/profile/[memberId]/page.tsx
index ba39e11d6..5f8cd7d97 100644
--- a/apps/web/app/[locale]/profile/[memberId]/page.tsx
+++ b/apps/web/app/[locale]/profile/[memberId]/page.tsx
@@ -32,7 +32,6 @@ const Profile = React.memo(function ProfilePage({ params }: { params: { memberId
const fullWidth = useRecoilValue(fullWidthState);
const [activityFilter, setActivityFilter] = useState('Tasks');
const setActivityTypeFilter = useSetRecoilState(activityTypeState);
-
const hook = useTaskFilter(profile);
const isManagerConnectedUser = activeTeamManagers.findIndex((member) => member.employee?.user?.id == user?.id);
@@ -69,6 +68,8 @@ const Profile = React.memo(function ProfilePage({ params }: { params: { memberId
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [profile.member]);
+ // Example usage
+
return (
<>
diff --git a/apps/web/app/hooks/features/useTaskInput.ts b/apps/web/app/hooks/features/useTaskInput.ts
index 134168405..5bc027d80 100644
--- a/apps/web/app/hooks/features/useTaskInput.ts
+++ b/apps/web/app/hooks/features/useTaskInput.ts
@@ -1,6 +1,6 @@
'use client';
-import { useAuthenticateUser, useModal, useSyncRef } from '@app/hooks';
+import { useAuthenticateUser, useModal, useSyncRef, useTaskStatus } from '@app/hooks';
import { useTeamTasks } from '@app/hooks/features/useTeamTasks';
import { ITaskLabelsItemList, Nullable } from '@app/interfaces';
import { ITaskStatus, ITeamTask } from '@app/interfaces/ITask';
@@ -36,7 +36,7 @@ export function useTaskInput({
} = {}) {
const { isOpen: isModalOpen, openModal, closeModal } = useModal();
const [closeableTask, setCloseableTaskTask] = useState(null);
-
+ const { taskStatus: taskStatusList } = useTaskStatus();
const {
tasks: teamTasks,
activeTeamTask,
@@ -140,11 +140,13 @@ export function useTaskInput({
}[];
} = {}) => {
if (query.trim().length < 2 || inputTask?.title === query.trim() || !userRef.current?.isEmailVerified) return;
-
+ const openId = taskStatusList.find((item) => item.value === 'open')?.id;
+ const statusId = taskStatusList.find((item) => item.name === taskStatus.current)?.id;
return createTask(
{
taskName: query.trim(),
issueType: taskIssue.current || 'Bug',
+ taskStatusId: statusId || openId as string,
status: taskStatus.current || undefined,
priority: taskPriority.current || undefined,
size: taskSize.current || undefined,
diff --git a/apps/web/app/hooks/features/useTeamTasks.ts b/apps/web/app/hooks/features/useTeamTasks.ts
index 8097779ab..e8dace649 100644
--- a/apps/web/app/hooks/features/useTeamTasks.ts
+++ b/apps/web/app/hooks/features/useTeamTasks.ts
@@ -215,6 +215,7 @@ export function useTeamTasks() {
{
taskName,
issueType,
+ taskStatusId,
status = taskStatus[0]?.name,
priority,
size,
@@ -224,6 +225,7 @@ export function useTeamTasks() {
taskName: string;
issueType?: string;
status?: string;
+ taskStatusId: string;
priority?: string;
size?: string;
tags?: ITaskLabelsItemList[];
@@ -231,13 +233,11 @@ export function useTeamTasks() {
},
members?: { id: string }[]
) => {
- const activeStatus = taskStatus.find((ts) => ts.name == status);
return createQueryCall(
{
title: taskName,
issueType,
status,
- taskStatusId: activeStatus?.id,
priority,
size,
tags,
@@ -249,7 +249,8 @@ export function useTeamTasks() {
}
: {}),
...(description ? { description: `${description}
` } : {}),
- ...(members ? { members } : {})
+ ...(members ? { members } : {}),
+ taskStatusId: taskStatusId,
},
$user.current
).then((res) => {
diff --git a/apps/web/components/shared/collaborate/index.tsx b/apps/web/components/shared/collaborate/index.tsx
index 8c4e08ee7..e760935ba 100644
--- a/apps/web/components/shared/collaborate/index.tsx
+++ b/apps/web/components/shared/collaborate/index.tsx
@@ -21,6 +21,7 @@ import stc from 'string-to-color';
import { JitsuAnalytics } from '../../../lib/components/services/jitsu-analytics';
import { useTranslations } from 'next-intl';
import { BrushSquareIcon, PhoneUpArrowIcon, UserLinearIcon } from 'assets/svg';
+import { ScrollArea } from '@components/ui/scroll-bar';
const Collaborate = () => {
const { onMeetClick, onBoardClick, collaborativeMembers, setCollaborativeMembers } = useCollaborative();
@@ -89,58 +90,64 @@ const Collaborate = () => {
{t('common.USER_NOT_FOUND')}
-
- {members.map((member) => (
- {
- handleMemberClick(member);
- }}
- >
-
+
+ {members.map((member) => (
+ {
+ handleMemberClick(member);
}}
>
- {(member?.image?.thumbUrl || member?.image?.fullUrl || member?.imageUrl) &&
- isValidUrl(
- member?.image?.thumbUrl || member?.image?.fullUrl || member?.imageUrl
- ) ? (
-
+ {(member?.image?.thumbUrl ||
+ member?.image?.fullUrl ||
+ member?.imageUrl) &&
+ isValidUrl(
+ member?.image?.thumbUrl ||
member?.image?.fullUrl ||
member?.imageUrl
- }
- alt="Team Avatar"
- imageTitle={member?.name || ''}
- >
- ) : member?.name ? (
- imgTitle(member?.name || ' ').charAt(0)
- ) : (
- ''
- )}
-
+ ) ? (
+
+ ) : member?.name ? (
+ imgTitle(member?.name || ' ').charAt(0)
+ ) : (
+ ''
+ )}
+
-
-
{member?.name}
-
{member?.email}
-
- {selectedMemberIds.includes(member?.id) ? (
-
- ) : null}
-
- ))}
-
+
+
{member?.name}
+
{member?.email}
+
+ {selectedMemberIds.includes(member?.id) ? (
+
+ ) : null}
+
+ ))}
+
+
diff --git a/apps/web/components/ui/scroll-bar.tsx b/apps/web/components/ui/scroll-bar.tsx
new file mode 100644
index 000000000..b94c3e717
--- /dev/null
+++ b/apps/web/components/ui/scroll-bar.tsx
@@ -0,0 +1,42 @@
+'use client';
+
+import * as React from 'react';
+import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
+import { clsxm } from '@app/utils';
+
+
+const ScrollArea = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+ {children}
+
+
+
+
+));
+ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
+
+const ScrollBar = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, orientation = 'vertical', ...props }, ref) => (
+
+
+
+));
+ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
+
+export { ScrollArea, ScrollBar };
diff --git a/apps/web/lib/components/image-overlapper.tsx b/apps/web/lib/components/image-overlapper.tsx
index 75e51c9d6..47b772154 100644
--- a/apps/web/lib/components/image-overlapper.tsx
+++ b/apps/web/lib/components/image-overlapper.tsx
@@ -3,6 +3,7 @@ import Image from 'next/image';
import Link from 'next/link';
import Skeleton from 'react-loading-skeleton';
import { Tooltip } from './tooltip';
+import { ScrollArea } from '@components/ui/scroll-bar';
export interface ImageOverlapperProps {
id: string;
url: string;
@@ -37,7 +38,7 @@ export default function ImageOverlapper({
className="relative "
>
{firstArray.map((image, index) => (
-
+
-
-
- {secondArray.map((image: ImageOverlapperProps, index: number) => {
- return (
-
+
+
+ {secondArray.map((image: ImageOverlapperProps, index: number) => {
+ return (
+
@@ -92,9 +94,10 @@ export default function ImageOverlapper({
{image.alt}
- );
- })}
-
+ );
+ })}
+
+
)}
diff --git a/apps/web/lib/features/task/task-item.tsx b/apps/web/lib/features/task/task-item.tsx
index a0f735665..0812df4ca 100644
--- a/apps/web/lib/features/task/task-item.tsx
+++ b/apps/web/lib/features/task/task-item.tsx
@@ -129,7 +129,7 @@ export function TaskAvatars({ task, limit = 2 }: { task: ITeamTask; limit?: numb
const size = 30;
return (
-
+
{t('common.MY_TASKS')}
diff --git a/apps/web/lib/settings/left-side-setting-menu.tsx b/apps/web/lib/settings/left-side-setting-menu.tsx
index 55d9e164c..83944101e 100644
--- a/apps/web/lib/settings/left-side-setting-menu.tsx
+++ b/apps/web/lib/settings/left-side-setting-menu.tsx
@@ -11,6 +11,7 @@ import { useTranslations } from 'next-intl';
import { useRecoilState } from 'recoil';
import Link from 'next/link';
import { clsxm } from '@app/utils';
+import { ScrollArea, ScrollBar } from '@components/ui/scroll-bar';
export const LeftSideSettingMenu = ({ className }: { className?: string }) => {
const t = useTranslations();
@@ -69,30 +70,31 @@ export const LeftSideSettingMenu = ({ className }: { className?: string }) => {
{t('common.SETTINGS')}
-
-
- {activePage === '/settings/personal' ? (
-
- ) : (
-
- )}
- {t('common.PERSONAL')}
- >
- }
- className="bg-transparent"
- textClassName={`
+
+
+
+ {activePage === '/settings/personal' ? (
+
+ ) : (
+
+ )}
+ {t('common.PERSONAL')}
+ >
+ }
+ className="bg-transparent"
+ textClassName={`
${
activePage === '/settings/personal'
? `text-[#3826a6] font-semibold`
: 'border-l-transparent font-normal dark:text-[#7E7991]'
}
`}
- wrapperClassName={`w-full border-t-0 border-r-0 border-b-0 rounded-none
+ wrapperClassName={`w-full border-t-0 border-r-0 border-b-0 rounded-none
font-normal text-[#7e7991] justify-start pt-[24px] pb-[24px] pl-[24px]
border-l-[5px] ${
activePage === '/settings/personal'
@@ -100,42 +102,46 @@ export const LeftSideSettingMenu = ({ className }: { className?: string }) => {
: 'border-l-transparent'
}
`}
- >
-
- {PersonalAccordianData.map((ad, index) => {
- return (
-
-
+
+ {PersonalAccordianData.map((ad, index) => {
+ return (
+
- {ad.title}
-
-
- );
- })}
-
-
+
+ {ad.title}
+
+
+ );
+ })}
+
+
-
- {activePage === '/settings/team' ? (
-
- ) : (
-
- )}
- {t('common.TEAM')}
- >
- }
- className="bg-[transparent]"
- textClassName={`${
- activePage === '/settings/team'
- ? ' text-[#3826a6] text-primary font-semibold'
- : ' border-l-transparent font-normal dark:text-[#7E7991]'
- }`}
- wrapperClassName={`w-full border-t-0 border-r-0 border-b-0 rounded-none
+
+ {activePage === '/settings/team' ? (
+
+ ) : (
+
+ )}
+ {t('common.TEAM')}
+ >
+ }
+ className="bg-[transparent]"
+ textClassName={`${
+ activePage === '/settings/team'
+ ? ' text-[#3826a6] text-primary font-semibold'
+ : ' border-l-transparent font-normal dark:text-[#7E7991]'
+ }`}
+ wrapperClassName={`w-full border-t-0 border-r-0 border-b-0 rounded-none
font-normal text-[#7e7991] justify-start text-sm pt-[24px] pb-[24px] pl-[24px]
border-l-[5px] ${
activePage === '/settings/team'
@@ -143,26 +149,32 @@ export const LeftSideSettingMenu = ({ className }: { className?: string }) => {
: ' border-l-transparent'
}
`}
- >
-
- {TeamAccordianData.filter((ad) => (!isTeamManager && !ad.managerOnly) || isTeamManager).map(
- (ad, index) => {
- return (
-
-
+
+ {TeamAccordianData.filter((ad) => (!isTeamManager && !ad.managerOnly) || isTeamManager).map(
+ (ad, index) => {
+ return (
+
- {ad.title}
-
-
- );
- }
- )}
-
-
-
+
+ {ad.title}
+
+
+ );
+ }
+ )}
+
+
+
+
+
);
};
diff --git a/apps/web/package.json b/apps/web/package.json
index 4908ee9bb..c079b71ef 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -35,6 +35,7 @@
"@radix-ui/react-hover-card": "^1.0.6",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-popover": "^1.0.6",
+ "@radix-ui/react-scroll-area": "^1.0.5",
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-toast": "^1.1.4",
diff --git a/yarn.lock b/yarn.lock
index bf7d3fd88..c4c5e04cc 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5424,6 +5424,22 @@
"@babel/runtime" "^7.13.10"
"@radix-ui/react-slot" "1.0.2"
+"@radix-ui/react-scroll-area@^1.0.5":
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-scroll-area/-/react-scroll-area-1.0.5.tgz#01160c6893f24a2ddb5aa399ae5b3ba84ad4d3cc"
+ integrity sha512-b6PAgH4GQf9QEn8zbT2XUHpW5z8BzqEc7Kl11TwDrvuTrxlkcjTD5qa/bxgKr+nmuXKu4L/W5UZ4mlP/VG/5Gw==
+ dependencies:
+ "@babel/runtime" "^7.13.10"
+ "@radix-ui/number" "1.0.1"
+ "@radix-ui/primitive" "1.0.1"
+ "@radix-ui/react-compose-refs" "1.0.1"
+ "@radix-ui/react-context" "1.0.1"
+ "@radix-ui/react-direction" "1.0.1"
+ "@radix-ui/react-presence" "1.0.1"
+ "@radix-ui/react-primitive" "1.0.3"
+ "@radix-ui/react-use-callback-ref" "1.0.1"
+ "@radix-ui/react-use-layout-effect" "1.0.1"
+
"@radix-ui/react-select@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-select/-/react-select-2.0.0.tgz#a3511792a51a7018d6559357323a7f52e0e38887"
@@ -7879,16 +7895,7 @@ axios@1.1.3:
form-data "^4.0.0"
proxy-from-env "^1.1.0"
-axios@^1.0.0, axios@^1.1.2:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.0.tgz#f1e5292f26b2fd5c2e66876adc5b06cdbd7d2102"
- integrity sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==
- dependencies:
- follow-redirects "^1.15.0"
- form-data "^4.0.0"
- proxy-from-env "^1.1.0"
-
-axios@^1.6.0:
+axios@^1.0.0, axios@^1.1.2, axios@^1.6.0:
version "1.6.8"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.8.tgz#66d294951f5d988a00e87a0ffb955316a619ea66"
integrity sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==