diff --git a/apps/web/app/[locale]/layout.tsx b/apps/web/app/[locale]/layout.tsx
index 7353f53b4..85dc858c7 100644
--- a/apps/web/app/[locale]/layout.tsx
+++ b/apps/web/app/[locale]/layout.tsx
@@ -17,6 +17,7 @@ import { PropsWithChildren, useEffect } from 'react';
import { useCheckAPI } from '@app/hooks/useCheckAPI';
import GlobalSkeleton from '@components/ui/global-skeleton';
+import OfflineWrapper from '@components/offline-wrapper';
import { JitsuOptions } from '@jitsu/jitsu-react/dist/useJitsu';
import { PHProvider } from './integration/posthog/provider';
@@ -145,14 +146,16 @@ const LocaleLayout = ({ children, params: { locale }, pageProps }: PropsWithChil
enableSystem
disableTransitionOnChange
>
- {loading && !pathname?.startsWith('/auth') ? (
-
- ) : (
- <>
-
- {children}
- >
- )}
+
+ {loading && !pathname?.startsWith('/auth') ? (
+
+ ) : (
+ <>
+
+ {children}
+ >
+ )}
+
diff --git a/apps/web/app/[locale]/page-component.tsx b/apps/web/app/[locale]/page-component.tsx
index 2a1ab3151..f8c5f696d 100644
--- a/apps/web/app/[locale]/page-component.tsx
+++ b/apps/web/app/[locale]/page-component.tsx
@@ -2,7 +2,7 @@
'use client';
import React, { useEffect, useState } from 'react';
-import { useOrganizationTeams, useTimerView } from '@app/hooks';
+import { useOrganizationTeams } from '@app/hooks';
import { clsxm } from '@app/utils';
import NoTeam from '@components/pages/main/no-team';
import { withAuthentication } from 'lib/app/authenticator';
@@ -10,8 +10,6 @@ import { Breadcrumb, Card, Container } from 'lib/components';
import { AuthUserTaskInput, TeamInvitations, TeamMembers, Timer, UnverifiedEmail } from 'lib/features';
import { MainLayout } from 'lib/layout';
import { IssuesView } from '@app/constants';
-import { useNetworkState } from '@uidotdev/usehooks';
-import Offline from '@components/pages/offline';
import { useTranslations } from 'next-intl';
import { Analytics } from '@vercel/analytics/react';
@@ -34,7 +32,6 @@ function MainPage() {
const t = useTranslations();
const [headerSize] = useState(10);
const { isTeamMember, isTrackingEnabled, activeTeam } = useOrganizationTeams();
- const { timerStatus } = useTimerView();
const [fullWidth, setFullWidth] = useAtom(fullWidthState);
const [view, setView] = useAtom(headerTabs);
@@ -44,7 +41,7 @@ function MainPage() {
{ title: activeTeam?.name || '', href: '/' },
{ title: t(`common.${view}`), href: `/` }
];
- const { online } = useNetworkState();
+
useEffect(() => {
if (view == IssuesView.KANBAN && path == '/') {
setView(IssuesView.CARDS);
@@ -57,13 +54,10 @@ function MainPage() {
setFullWidth(JSON.parse(window?.localStorage.getItem('conf-fullWidth-mode') || 'true'));
}, [setFullWidth]);
- if (!online) {
- return ;
- }
return (
<>
- {/*
*/}
+ {/*
*/}
-
+
-
@@ -100,7 +94,7 @@ function MainPage() {
footerClassName={clsxm('')}
>
-
{isTeamMember ?
+
{isTeamMember ?
diff --git a/apps/web/components/offline-wrapper/index.tsx b/apps/web/components/offline-wrapper/index.tsx
new file mode 100644
index 000000000..d56797850
--- /dev/null
+++ b/apps/web/components/offline-wrapper/index.tsx
@@ -0,0 +1,37 @@
+'use client';
+
+import { useNetworkState } from '@uidotdev/usehooks';
+import Offline from '@components/pages/offline';
+import { useTimerView } from '@app/hooks';
+import { usePathname } from 'next/navigation';
+
+interface OfflineWrapperProps {
+ children: React.ReactNode;
+}
+
+/**
+ * A wrapper component that conditionally renders the Offline component if the user is not online.
+ * The Offline component is not shown on authentication pages (paths starting with /auth).
+ * When the user is offline, the Offline component is rendered with the showTimer prop set to
+ * whether the timer is running or not.
+ *
+ * @example
+ *
+ *
+ *
+ * @param {React.ReactNode} children - The children components to render when the user is online
+ * @returns {React.ReactElement} - The Offline component if the user is offline (except on auth pages), or the children components if the user is online
+ */
+export default function OfflineWrapper({ children }: OfflineWrapperProps) {
+ const { online } = useNetworkState();
+ const { timerStatus } = useTimerView();
+ const pathname = usePathname();
+
+ const isAuthPage = pathname?.startsWith('/auth');
+
+ if (!online && !isAuthPage) {
+ return
;
+ }
+
+ return <>{children}>;
+}
diff --git a/apps/web/components/pages/offline/index.tsx b/apps/web/components/pages/offline/index.tsx
index 198e689df..dec2f2754 100644
--- a/apps/web/components/pages/offline/index.tsx
+++ b/apps/web/components/pages/offline/index.tsx
@@ -3,11 +3,14 @@ import { cn } from '@/lib/utils';
import SadCry from '@components/ui/svgs/sad-cry';
import { Text } from 'lib/components';
import { useTranslations } from 'next-intl';
+
interface IPropsOffline {
showTimer?: boolean
}
+
function Offline({ showTimer }: IPropsOffline) {
const t = useTranslations();
+
return (