new menu structure tested new version will be deployed
This commit is contained in:
parent
6ce95b5df6
commit
b714585a2e
|
|
@ -31,49 +31,49 @@ services:
|
||||||
# cpus: 1
|
# cpus: 1
|
||||||
# mem_limit: 2048m
|
# mem_limit: 2048m
|
||||||
|
|
||||||
account_service:
|
# account_service:
|
||||||
container_name: account_service
|
# container_name: account_service
|
||||||
build:
|
# build:
|
||||||
context: .
|
# context: .
|
||||||
dockerfile: api_services/api_builds/account_service/Dockerfile
|
# dockerfile: api_services/api_builds/account_service/Dockerfile
|
||||||
env_file:
|
# env_file:
|
||||||
- api_env.env
|
# - api_env.env
|
||||||
networks:
|
# networks:
|
||||||
- wag-services
|
# - wag-services
|
||||||
environment:
|
# environment:
|
||||||
- API_PATH=app:app
|
# - API_PATH=app:app
|
||||||
- API_HOST=0.0.0.0
|
# - API_HOST=0.0.0.0
|
||||||
- API_PORT=8004
|
# - API_PORT=8004
|
||||||
- API_LOG_LEVEL=info
|
# - API_LOG_LEVEL=info
|
||||||
- API_RELOAD=1
|
# - API_RELOAD=1
|
||||||
- API_APP_NAME=evyos-account-api-gateway
|
# - API_APP_NAME=evyos-account-api-gateway
|
||||||
- API_TITLE=WAG API Account Api Gateway
|
# - API_TITLE=WAG API Account Api Gateway
|
||||||
- API_DESCRIPTION=This api is serves as web account api gateway only to evyos web services.
|
# - API_DESCRIPTION=This api is serves as web account api gateway only to evyos web services.
|
||||||
- API_APP_URL=https://account_service
|
# - API_APP_URL=https://account_service
|
||||||
ports:
|
# ports:
|
||||||
- "8004:8004"
|
# - "8004:8004"
|
||||||
|
|
||||||
building_service:
|
# building_service:
|
||||||
container_name: building_service
|
# container_name: building_service
|
||||||
build:
|
# build:
|
||||||
context: .
|
# context: .
|
||||||
dockerfile: api_services/api_builds/building_service/Dockerfile
|
# dockerfile: api_services/api_builds/building_service/Dockerfile
|
||||||
env_file:
|
# env_file:
|
||||||
- api_env.env
|
# - api_env.env
|
||||||
networks:
|
# networks:
|
||||||
- wag-services
|
# - wag-services
|
||||||
environment:
|
# environment:
|
||||||
- API_PATH=app:app
|
# - API_PATH=app:app
|
||||||
- API_HOST=0.0.0.0
|
# - API_HOST=0.0.0.0
|
||||||
- API_PORT=8006
|
# - API_PORT=8006
|
||||||
- API_LOG_LEVEL=info
|
# - API_LOG_LEVEL=info
|
||||||
- API_RELOAD=1
|
# - API_RELOAD=1
|
||||||
- API_APP_NAME=evyos-building-api-gateway
|
# - API_APP_NAME=evyos-building-api-gateway
|
||||||
- API_TITLE=WAG API Building Api Gateway
|
# - API_TITLE=WAG API Building Api Gateway
|
||||||
- API_DESCRIPTION=This api is serves as web building api gateway only to evyos web services.
|
# - API_DESCRIPTION=This api is serves as web building api gateway only to evyos web services.
|
||||||
- API_APP_URL=https://building_service
|
# - API_APP_URL=https://building_service
|
||||||
ports:
|
# ports:
|
||||||
- "8006:8006"
|
# - "8006:8006"
|
||||||
|
|
||||||
identity_service:
|
identity_service:
|
||||||
container_name: identity_service
|
container_name: identity_service
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,7 @@ const MainEnPage: React.FC<MaindasboardPageProps> = async ({ params, searchParam
|
||||||
const searchParameters = await searchParams;
|
const searchParameters = await searchParams;
|
||||||
const tokenValid = await checkAccessTokenIsValid()
|
const tokenValid = await checkAccessTokenIsValid()
|
||||||
if (!tokenValid) { redirect("/auth/login") }
|
if (!tokenValid) { redirect("/auth/login") }
|
||||||
return (
|
return <div className="flex flex-col items-center justify-center"><DashboardLayout params={parameters} searchParams={searchParameters} lang="en" /></div>
|
||||||
<div className="flex flex-col items-center justify-center">
|
|
||||||
<DashboardLayout params={parameters} searchParams={searchParameters} lang="en" />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MainEnPage;
|
export default MainEnPage;
|
||||||
|
|
|
||||||
|
|
@ -3,33 +3,28 @@ import ContentToRenderNoPage from "@/pages/mutual/noContent/page";
|
||||||
import pageIndexMulti from "@/pages/multi/index";
|
import pageIndexMulti from "@/pages/multi/index";
|
||||||
|
|
||||||
const PageToBeChildrendMulti: React.FC<ContentProps> = ({
|
const PageToBeChildrendMulti: React.FC<ContentProps> = ({
|
||||||
lang,
|
|
||||||
activePageUrl,
|
activePageUrl,
|
||||||
mode,
|
|
||||||
userData,
|
userData,
|
||||||
userLoading,
|
userLoading,
|
||||||
userError,
|
userError,
|
||||||
selectionData,
|
onlineData,
|
||||||
selectionLoading,
|
onlineLoading,
|
||||||
selectionError,
|
onlineError,
|
||||||
useReloadWindow
|
searchParams,
|
||||||
|
refreshOnline,
|
||||||
|
updateOnline,
|
||||||
|
refreshUser,
|
||||||
|
updateUser,
|
||||||
}) => {
|
}) => {
|
||||||
const pageComponents = pageIndexMulti[activePageUrl];
|
const pageComponents = pageIndexMulti[activePageUrl];
|
||||||
if (!pageComponents) { return <ContentToRenderNoPage lang={lang} /> }
|
if (!pageComponents) { return <ContentToRenderNoPage lang={onlineData.lang} /> }
|
||||||
const ComponentKey = Object.keys(pageComponents)[0];
|
const ComponentKey = Object.keys(pageComponents)[0];
|
||||||
const PageComponent = pageComponents[ComponentKey];
|
const PageComponent = pageComponents[ComponentKey];
|
||||||
if (!PageComponent) { return <ContentToRenderNoPage lang={lang} /> }
|
if (!PageComponent) { return <ContentToRenderNoPage lang={onlineData.lang} /> }
|
||||||
return <PageComponent
|
return <PageComponent
|
||||||
lang={lang}
|
activePageUrl={activePageUrl} searchParams={searchParams}
|
||||||
activePageUrl={activePageUrl}
|
userData={userData} userLoading={userLoading} userError={userError} refreshUser={refreshUser} updateUser={updateUser}
|
||||||
mode={mode}
|
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline}
|
||||||
userData={userData}
|
|
||||||
userLoading={userLoading}
|
|
||||||
userError={userError}
|
|
||||||
selectionData={selectionData}
|
|
||||||
selectionLoading={selectionLoading}
|
|
||||||
selectionError={selectionError}
|
|
||||||
useReloadWindow={useReloadWindow}
|
|
||||||
/>;
|
/>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,82 +1,68 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
import { FC, Suspense, memo } from "react";
|
||||||
import { FC, Suspense, useMemo, memo } from "react";
|
|
||||||
import { ContentProps, ModeTypes, ModeTypesList } from "@/validations/mutual/dashboard/props";
|
import { ContentProps, ModeTypes, ModeTypesList } from "@/validations/mutual/dashboard/props";
|
||||||
|
import { LanguageTypes } from "@/validations/mutual/language/validations";
|
||||||
import PageToBeChildrendMulti from "./PageToBeChildrendMulti";
|
import PageToBeChildrendMulti from "./PageToBeChildrendMulti";
|
||||||
import LoadingContent from "@/components/mutual/loader/component";
|
import LoadingContent from "@/components/mutual/loader/component";
|
||||||
|
|
||||||
// Create a memoized version of PageToBeChildrendMulti to prevent unnecessary re-renders
|
|
||||||
const MemoizedMultiPage = memo(PageToBeChildrendMulti);
|
const MemoizedMultiPage = memo(PageToBeChildrendMulti);
|
||||||
|
|
||||||
// const ContentComponent: FC<ContentProps> = async ({ lang, translations, activePageUrl, isMulti, mode }) => {
|
const translations = {
|
||||||
// const modeFromQuery = ModeTypesList.includes(mode || '') ? mode : 'shortList'
|
en: {
|
||||||
// const renderProps = { lang, translations, activePageUrl, mode: modeFromQuery as ModeTypes }
|
errorLoadingContent: "Error Loading Content",
|
||||||
// const PageToBeChildrend = isMulti ? PageToBeChildrendMulti : PageToBeChildrendSingle
|
contentArea: "Content Area",
|
||||||
// const loadingContent = <LoadingContent height="h-16" size="w-36 h-48" plane="h-full w-full" />
|
contentLoading: "Content Loading",
|
||||||
// const classNameDiv = "fixed top-24 left-80 right-0 py-10 px-15 border-emerald-150 border-l-2 overflow-y-auto h-[calc(100vh-64px)]"
|
contentLoadingDescription: "The requested page is currently unavailable or still loading.",
|
||||||
// return <div className={classNameDiv}><Suspense fallback={loadingContent}><PageToBeChildrend {...renderProps} /></Suspense></div>
|
pageUrl: "Page URL",
|
||||||
// };
|
language: "Language",
|
||||||
|
},
|
||||||
|
tr: {
|
||||||
|
errorLoadingContent: "İçerik Yüklenirken Hata",
|
||||||
|
contentArea: "İçerik Alanı",
|
||||||
|
contentLoading: "İçerik Yükleniyor",
|
||||||
|
contentLoadingDescription: "İçerik Yüklenirken Hata",
|
||||||
|
pageUrl: "Sayfa URL",
|
||||||
|
language: "Dil",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Static fallback component to avoid state updates during render
|
const FallbackContent: FC<{ lang: LanguageTypes; activePageUrl: string }> = memo(({ lang, activePageUrl }) => (
|
||||||
const FallbackContent: FC<{ lang: string; activePageUrl: string; mode: string }> = memo(({ lang, activePageUrl, mode }) => (
|
|
||||||
<div className="p-6 bg-white rounded-lg shadow-md">
|
<div className="p-6 bg-white rounded-lg shadow-md">
|
||||||
<h2 className="text-2xl font-bold mb-4">Content Loading</h2>
|
<h2 className="text-2xl font-bold mb-4">{translations[lang].contentLoading}</h2>
|
||||||
<p className="text-gray-600 mb-4">The requested page is currently unavailable or still loading.</p>
|
<p className="text-gray-600 mb-4">{translations[lang].contentLoadingDescription}</p>
|
||||||
<div className="p-4 bg-blue-50 border border-blue-200 rounded-md">
|
<div className="p-4 bg-blue-50 border border-blue-200 rounded-md">
|
||||||
<p className="text-sm text-blue-700">Page URL: {activePageUrl}</p>
|
<p className="text-sm text-blue-700">{translations[lang].pageUrl}: {activePageUrl}</p>
|
||||||
<p className="text-sm text-blue-700">Language: {lang}</p>
|
<p className="text-sm text-blue-700">{translations[lang].language}: {lang}</p>
|
||||||
<p className="text-sm text-blue-700">Mode: {mode}</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
));
|
));
|
||||||
|
|
||||||
const ContentComponent: FC<ContentProps> = ({
|
const ContentComponent: FC<ContentProps> = ({
|
||||||
lang, activePageUrl, mode,
|
searchParams, activePageUrl, mode, userData, userLoading, userError, refreshUser, updateUser,
|
||||||
userData, userLoading, userError,
|
onlineData, onlineLoading, onlineError, refreshOnline, updateOnline,
|
||||||
selectionData, selectionLoading, selectionError,
|
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
const page = useMemo(() => { const extractedPage = activePageUrl.split('/').pop(); return extractedPage }, [activePageUrl]);
|
|
||||||
const modeFromQuery: string = ModeTypesList.includes(mode || '') ? (mode || 'shortList') : 'shortList';
|
|
||||||
const loadingContent = <LoadingContent height="h-16" size="w-36 h-48" plane="h-full w-full" />;
|
const loadingContent = <LoadingContent height="h-16" size="w-36 h-48" plane="h-full w-full" />;
|
||||||
const classNameDiv = "fixed top-24 left-80 right-0 py-10 px-15 border-emerald-150 border-l-2 overflow-y-auto h-[calc(100vh-64px)]";
|
const classNameDiv = "fixed top-24 left-80 right-0 py-10 px-15 border-emerald-150 border-l-2 overflow-y-auto h-[calc(100vh-64px)]";
|
||||||
|
const lang = onlineData?.lang as LanguageTypes || 'en';
|
||||||
|
|
||||||
if (selectionLoading || userLoading) { return <div className={classNameDiv}>{loadingContent}</div> }
|
if (userLoading) { return <div className={classNameDiv}>{loadingContent}</div> }
|
||||||
if (selectionError || userError) {
|
if (userError) {
|
||||||
return <div className={classNameDiv}>
|
return (
|
||||||
<div className="p-6 bg-white rounded-lg shadow-md">
|
<div className={classNameDiv}><div className="p-6 bg-white rounded-lg shadow-md">
|
||||||
<h2 className="text-2xl font-bold mb-4 text-red-600">Error Loading Content</h2>
|
<h2 className="text-2xl font-bold mb-4 text-red-600">{translations[lang].errorLoadingContent}</h2><p className="text-gray-600 mb-4">{userError}</p></div>
|
||||||
<p className="text-gray-600 mb-4">{selectionError || userError}</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className={classNameDiv}>
|
<div className={classNameDiv}>
|
||||||
<Suspense fallback={loadingContent}>
|
<Suspense fallback={loadingContent}>
|
||||||
<div className="p-6 bg-white rounded-lg shadow-md">
|
<div className="p-6 bg-white rounded-lg shadow-md">
|
||||||
<h2 className="text-2xl font-bold mb-4">Content Area</h2>
|
<h2 className="text-2xl font-bold mb-4">{translations[lang].contentArea}</h2>
|
||||||
|
{(!userData) && (<FallbackContent lang={lang} activePageUrl={activePageUrl || ''} />)}
|
||||||
{/* Fallback Content */}
|
|
||||||
{(!userData || !selectionData) && (
|
|
||||||
<FallbackContent
|
|
||||||
lang={lang || ''}
|
|
||||||
activePageUrl={activePageUrl || ''}
|
|
||||||
mode={modeFromQuery}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Wrap component in memo to prevent unnecessary re-renders */}
|
|
||||||
<MemoizedMultiPage
|
<MemoizedMultiPage
|
||||||
lang={lang || ''}
|
activePageUrl={activePageUrl || ''} searchParams={searchParams}
|
||||||
activePageUrl={activePageUrl || ''}
|
userData={userData} userLoading={userLoading} userError={userError} refreshUser={refreshUser} updateUser={updateUser}
|
||||||
mode={modeFromQuery as ModeTypes}
|
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline} />
|
||||||
userData={userData}
|
|
||||||
userLoading={userLoading}
|
|
||||||
userError={userError}
|
|
||||||
selectionData={selectionData}
|
|
||||||
selectionLoading={selectionLoading}
|
|
||||||
selectionError={selectionError}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { langGetKey } from "@/lib/langGet";
|
import { langGetKey } from "@/lib/langGet";
|
||||||
import { FooterProps } from "@/validations/mutual/dashboard/props";
|
import { FooterProps } from "@/validations/mutual/dashboard/props";
|
||||||
|
import { LanguageTypes } from "@/validations/mutual/language/validations";
|
||||||
|
|
||||||
const translations = {
|
const translations = {
|
||||||
en: {
|
en: {
|
||||||
|
|
@ -15,9 +16,11 @@ const translations = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const FooterComponent: FC<FooterProps> = ({
|
const FooterComponent: FC<FooterProps> = ({
|
||||||
lang, activePageUrl, useReloadWindow, configData, configLoading, configError
|
activePageUrl, configData, configLoading, configError,
|
||||||
|
onlineData, onlineLoading, onlineError
|
||||||
}) => {
|
}) => {
|
||||||
// Use the config context hook
|
// Use the config context hook
|
||||||
|
const lang = onlineData?.lang as LanguageTypes || 'en';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed text-center bottom-0 left-0 right-0 h-16 p-4 border-t border-emerald-150 border-t-2 shadow-sm backdrop-blur-sm bg-emerald-50">
|
<div className="fixed text-center bottom-0 left-0 right-0 h-16 p-4 border-t border-emerald-150 border-t-2 shadow-sm backdrop-blur-sm bg-emerald-50">
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { FC } from "react";
|
||||||
import { HeaderProps } from "@/validations/mutual/dashboard/props";
|
import { HeaderProps } from "@/validations/mutual/dashboard/props";
|
||||||
import { langGetKey } from "@/lib/langGet";
|
import { langGetKey } from "@/lib/langGet";
|
||||||
import LanguageSelectionComponent from "@/components/mutual/languageSelection/component";
|
import LanguageSelectionComponent from "@/components/mutual/languageSelection/component";
|
||||||
|
import { LanguageTypes } from "@/validations/mutual/language/validations";
|
||||||
|
|
||||||
const translations = {
|
const translations = {
|
||||||
en: {
|
en: {
|
||||||
|
|
@ -16,10 +17,10 @@ const translations = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const HeaderComponent: FC<HeaderProps> = ({
|
const HeaderComponent: FC<HeaderProps> = ({
|
||||||
lang, activePageUrl, prefix, mode,
|
activePageUrl, onlineData, onlineLoading, onlineError, refreshOnline, updateOnline,
|
||||||
onlineData, onlineLoading, onlineError, refreshOnline, updateOnline,
|
userData, userLoading, userError, refreshUser, updateUser
|
||||||
userData, userLoading, userError,
|
|
||||||
}) => {
|
}) => {
|
||||||
|
const lang = onlineData?.lang as LanguageTypes || 'en';
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-between h-24 items-center p-4 border-emerald-150 border-b-2 shadow-sm backdrop-blur-sm sticky top-0 z-50 bg-emerald-50">
|
<div className="flex justify-between h-24 items-center p-4 border-emerald-150 border-b-2 shadow-sm backdrop-blur-sm sticky top-0 z-50 bg-emerald-50">
|
||||||
<div className="flex flex-row justify-center items-center">
|
<div className="flex flex-row justify-center items-center">
|
||||||
|
|
@ -29,12 +30,11 @@ const HeaderComponent: FC<HeaderProps> = ({
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
{!onlineLoading && onlineData && onlineData.userType && (
|
{!onlineLoading && onlineData && onlineData.userType && (
|
||||||
<div className="mr-4 text-sm">
|
<div className="mr-4 text-sm">
|
||||||
<span className="font-semibold">{onlineData.lang || lang}</span>
|
<span className="font-semibold">{lang}</span>
|
||||||
<span className="ml-2 text-xs bg-green-100 text-green-800 px-2 py-1 rounded-full">{onlineData.userType}</span>
|
<span className="ml-2 text-xs bg-green-100 text-green-800 px-2 py-1 rounded-full">{onlineData.userType}</span>
|
||||||
</div>
|
</div>
|
||||||
)}<LanguageSelectionComponent
|
)}<LanguageSelectionComponent
|
||||||
lang={lang} activePage={activePageUrl} prefix={prefix}
|
activePage={activePageUrl} onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline}
|
||||||
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { FC, Suspense } from "react";
|
import { FC, Suspense } from "react";
|
||||||
import { MenuProps } from "@/validations/mutual/dashboard/props";
|
import { MenuProps } from "@/validations/mutual/dashboard/props";
|
||||||
|
import { LanguageTypes } from "@/validations/mutual/language/validations";
|
||||||
|
|
||||||
import UserProfileSection from "./userProfileSection";
|
import UserProfileSection from "./userProfileSection";
|
||||||
import ClientSelectionSection from "./clientSelectionSection";
|
import ClientSelectionSection from "./clientSelectionSection";
|
||||||
|
|
@ -11,7 +12,7 @@ import MenuEmptyState from "./menuEmptyState";
|
||||||
import LoadingContent from "@/components/mutual/loader/component";
|
import LoadingContent from "@/components/mutual/loader/component";
|
||||||
|
|
||||||
const MenuComponent: FC<MenuProps> = ({
|
const MenuComponent: FC<MenuProps> = ({
|
||||||
lang, activePageUrl, useReloadWindow, availableApplications,
|
activePageUrl, availableApplications, prefix,
|
||||||
onlineData, onlineLoading, onlineError,
|
onlineData, onlineLoading, onlineError,
|
||||||
userData, userLoading, userError,
|
userData, userLoading, userError,
|
||||||
selectionData, selectionLoading, selectionError,
|
selectionData, selectionLoading, selectionError,
|
||||||
|
|
@ -21,21 +22,21 @@ const MenuComponent: FC<MenuProps> = ({
|
||||||
if (menuError) { return <MenuErrorState error={menuError} />; } // Render error state
|
if (menuError) { return <MenuErrorState error={menuError} />; } // Render error state
|
||||||
if (availableApplications.length === 0) { return <MenuEmptyState />; } // Render empty state
|
if (availableApplications.length === 0) { return <MenuEmptyState />; } // Render empty state
|
||||||
function handleClientSelection(client: any) { console.log('Client selected:', client) }
|
function handleClientSelection(client: any) { console.log('Client selected:', client) }
|
||||||
|
const lang = onlineData?.lang as LanguageTypes || 'en';
|
||||||
return (
|
return (
|
||||||
<div className="fixed top-24 p-5 left-0 right-0 w-80 border-emerald-150 border-r-2 overflow-y-auto h-[calc(100vh-6rem)]">
|
<div className="fixed top-24 p-5 left-0 right-0 w-80 border-emerald-150 border-r-2 overflow-y-auto h-[calc(100vh-6rem)]">
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
{/* User Profile Section */}
|
{/* User Profile Section */}
|
||||||
<Suspense fallback={<div><LoadingContent height="h-16" size="w-36 h-48" key={"loading-conent"} plane="h-full w-full" /></div>}>
|
<Suspense fallback={<div><LoadingContent height="h-16" size="w-36 h-48" key={"loading-content"} plane="h-full w-full" /></div>}>
|
||||||
<UserProfileSection userData={userData} onlineData={onlineData} />
|
<UserProfileSection userData={userData} onlineData={onlineData} />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
{/* Client Selection Section */}
|
{/* Client Selection Section */}
|
||||||
<Suspense fallback={<div><LoadingContent height="h-16" size="w-36 h-48" key={"loading-conent"} plane="h-full w-full" /></div>}>
|
<Suspense fallback={<div><LoadingContent height="h-16" size="w-36 h-48" key={"loading-content"} plane="h-full w-full" /></div>}>
|
||||||
<ClientSelectionSection selectionData={selectionData} initialSelectedClient={selectionData} onClientSelect={handleClientSelection} />
|
<ClientSelectionSection selectionData={selectionData} initialSelectedClient={selectionData} onClientSelect={handleClientSelection} />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
|
||||||
{/* Menu Items Section */}
|
{/* Menu Items Section */}
|
||||||
<Suspense fallback={<div><LoadingContent height="h-16" size="w-36 h-48" key={"loading-conent"} plane="h-full w-full" /></div>}>
|
<Suspense fallback={<div><LoadingContent height="h-16" size="w-36 h-48" key={"loading-content"} plane="h-full w-full" /></div>}>
|
||||||
<MenuItemsSection availableApplications={availableApplications} activePageUrl={activePageUrl} lang={lang} />
|
<MenuItemsSection availableApplications={availableApplications} activePageUrl={activePageUrl} lang={lang} prefix={prefix} />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
import React, { FC, useEffect, useState } from "react";
|
||||||
import { FC, useState, useEffect } from "react";
|
import { menuTranslation } from "@/languages/mutual/menu";
|
||||||
import FirstLayerDropdown from "./firstLayerComponent";
|
import FirstLayerDropdown from "./firstLayerComponent";
|
||||||
import SecondLayerDropdown from "./secondLayerComponent";
|
import SecondLayerDropdown from "./secondLayerComponent";
|
||||||
import ThirdLayerDropdown from "./thirdLayerComponent";
|
import ThirdLayerDropdown from "./thirdLayerComponent";
|
||||||
import { parseURlFormString } from "@/lib/menuGet";
|
|
||||||
import { menuTranslation } from "@/languages/mutual/menu";
|
|
||||||
|
|
||||||
// Define types for menu structure
|
type TranslationItem = { value: string; key: string };
|
||||||
type ThirdLayerItem = Record<string, any>;
|
type ThirdLayerItemData = { path: string; translation: TranslationItem[] };
|
||||||
|
type ThirdLayerItem = Record<string, ThirdLayerItemData>;
|
||||||
type SecondLayerItems = Record<string, ThirdLayerItem>;
|
type SecondLayerItems = Record<string, ThirdLayerItem>;
|
||||||
type FirstLayerItems = Record<string, SecondLayerItems>;
|
type FirstLayerItems = Record<string, SecondLayerItems>;
|
||||||
type MenuStructure = FirstLayerItems;
|
type MenuStructure = FirstLayerItems;
|
||||||
|
|
@ -17,159 +16,86 @@ interface MenuItemsSectionProps {
|
||||||
availableApplications: string[];
|
availableApplications: string[];
|
||||||
activePageUrl: string;
|
activePageUrl: string;
|
||||||
lang: string;
|
lang: string;
|
||||||
|
prefix?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to get translation for a URL path
|
const menuStaticTranslation = {
|
||||||
const getMenuTranslation = (translations: any, urlPath: string) => {
|
tr: { menu: "Menü" },
|
||||||
if (translations[urlPath]) {
|
en: { menu: "Menu" }
|
||||||
return translations[urlPath];
|
}
|
||||||
}
|
|
||||||
const cleanPath = urlPath.startsWith('/') ? urlPath.substring(1) : urlPath;
|
|
||||||
if (translations[cleanPath]) {
|
|
||||||
return translations[cleanPath];
|
|
||||||
}
|
|
||||||
const pathWithSlash = urlPath.startsWith('/') ? urlPath : `/${urlPath}`;
|
|
||||||
if (translations[pathWithSlash]) {
|
|
||||||
return translations[pathWithSlash];
|
|
||||||
}
|
|
||||||
const keys = Object.keys(translations);
|
|
||||||
for (const key of keys) {
|
|
||||||
const cleanKey = key.startsWith('/') ? key.substring(1) : key;
|
|
||||||
const cleanUrlPath = urlPath.startsWith('/') ? urlPath.substring(1) : urlPath;
|
|
||||||
|
|
||||||
if (cleanUrlPath.includes(cleanKey) || cleanKey.includes(cleanUrlPath)) {
|
const MenuItemsSection: FC<MenuItemsSectionProps> = ({ availableApplications, activePageUrl, lang, prefix }) => {
|
||||||
return translations[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const parts = urlPath.split('/');
|
|
||||||
return parts[parts.length - 1] || urlPath;
|
|
||||||
};
|
|
||||||
|
|
||||||
const MenuItemsSection: FC<MenuItemsSectionProps> = ({ availableApplications, activePageUrl, lang }) => {
|
|
||||||
const [expandedFirstLayer, setExpandedFirstLayer] = useState<string | null>(null);
|
const [expandedFirstLayer, setExpandedFirstLayer] = useState<string | null>(null);
|
||||||
const [expandedSecondLayer, setExpandedSecondLayer] = useState<string | null>(null);
|
const [expandedSecondLayer, setExpandedSecondLayer] = useState<string | null>(null);
|
||||||
const [menuStructure, setMenuStructure] = useState<MenuStructure>({});
|
const [menuStructure, setMenuStructure] = useState<MenuStructure>({});
|
||||||
|
|
||||||
const menuTranslationWLang = menuTranslation[lang as keyof typeof menuTranslation];
|
const menuTranslationWLang = menuTranslation[lang as keyof typeof menuTranslation];
|
||||||
const activePathLayers = parseURlFormString(activePageUrl).data;
|
const activeParsedLayer = (menuTranslationWLang[activePageUrl as keyof typeof menuTranslationWLang] as unknown as TranslationItem[]) || [];
|
||||||
const activeFirstLayer = activePathLayers[0] || null;
|
const activeFirstLayer = activeParsedLayer[0] ? activeParsedLayer[0].key : null;
|
||||||
const activeSecondLayer = activePathLayers[1] || null;
|
const activeSecondLayer = activeParsedLayer[1] ? activeParsedLayer[1].key : null;
|
||||||
const activeThirdLayer = activePathLayers.slice(2, activePathLayers.length).join("/");
|
const activeThirdLayer = activeParsedLayer[2] ? activeParsedLayer[2].key : null;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const newMenuStructure: MenuStructure = {};
|
const newMenuStructure: MenuStructure = {};
|
||||||
availableApplications.forEach((appPath: string) => {
|
availableApplications.forEach((appPath: string) => {
|
||||||
const cleanPath = appPath.startsWith('/') ? appPath.substring(1) : appPath;
|
const pathTranslation = menuTranslationWLang[appPath as keyof typeof menuTranslationWLang] as unknown as TranslationItem[] | undefined;
|
||||||
const pathParts = cleanPath.split('/');
|
if (pathTranslation && pathTranslation.length >= 3) {
|
||||||
if (pathParts.length >= 3) {
|
const firstLayer = pathTranslation[0] ? pathTranslation[0].key : '';
|
||||||
const firstLayer = pathParts[0];
|
const secondLayer = pathTranslation[1] ? pathTranslation[1].key : '';
|
||||||
const secondLayer = pathParts[1];
|
const thirdLayer = pathTranslation[2] ? pathTranslation[2].key : '';
|
||||||
const thirdLayer = pathParts.slice(2).join('/');
|
|
||||||
if (!newMenuStructure[firstLayer]) { newMenuStructure[firstLayer] = {} }
|
if (!newMenuStructure[firstLayer]) { newMenuStructure[firstLayer] = {} }
|
||||||
if (!newMenuStructure[firstLayer][secondLayer]) { newMenuStructure[firstLayer][secondLayer] = {} }
|
if (!newMenuStructure[firstLayer][secondLayer]) { newMenuStructure[firstLayer][secondLayer] = {} }
|
||||||
newMenuStructure[firstLayer][secondLayer][thirdLayer] = true;
|
newMenuStructure[firstLayer][secondLayer][thirdLayer] = { path: appPath, translation: pathTranslation };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
setMenuStructure(newMenuStructure);
|
setMenuStructure(newMenuStructure);
|
||||||
}, [availableApplications]);
|
}, [availableApplications, menuTranslationWLang]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => { if (activeFirstLayer) { setExpandedFirstLayer(activeFirstLayer); if (activeSecondLayer) { setExpandedSecondLayer(activeSecondLayer) } } }, [activeFirstLayer, activeSecondLayer]);
|
||||||
if (activeFirstLayer) {
|
|
||||||
setExpandedFirstLayer(activeFirstLayer);
|
|
||||||
if (activeSecondLayer) {
|
|
||||||
setExpandedSecondLayer(activeSecondLayer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [activeFirstLayer, activeSecondLayer]);
|
|
||||||
|
|
||||||
const handleFirstLayerClick = (key: string) => {
|
|
||||||
if (expandedFirstLayer === key) {
|
|
||||||
setExpandedFirstLayer(null);
|
|
||||||
setExpandedSecondLayer(null)
|
|
||||||
} else {
|
|
||||||
setExpandedFirstLayer(key);
|
|
||||||
setExpandedSecondLayer(null)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSecondLayerClick = (key: string) => {
|
|
||||||
if (expandedSecondLayer === key) {
|
|
||||||
setExpandedSecondLayer(null)
|
|
||||||
} else {
|
|
||||||
setExpandedSecondLayer(key)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
const handleFirstLayerClick = (key: string) => { if (expandedFirstLayer === key) { setExpandedFirstLayer(null); setExpandedSecondLayer(null) } else { setExpandedFirstLayer(key); setExpandedSecondLayer(null) } };
|
||||||
|
const handleSecondLayerClick = (key: string) => { if (expandedSecondLayer === key) { setExpandedSecondLayer(null) } else { setExpandedSecondLayer(key) } };
|
||||||
const renderThirdLayerItems = (firstLayerKey: string, secondLayerKey: string, thirdLayerItems: ThirdLayerItem) => {
|
const renderThirdLayerItems = (firstLayerKey: string, secondLayerKey: string, thirdLayerItems: ThirdLayerItem) => {
|
||||||
const baseUrl = `/${firstLayerKey}/${secondLayerKey}`;
|
return Object.entries(thirdLayerItems).map(([thirdLayerKey, itemData]) => {
|
||||||
return Object.keys(thirdLayerItems).map(thirdLayerKey => {
|
|
||||||
const isActive = activeFirstLayer === firstLayerKey && activeSecondLayer === secondLayerKey && activeThirdLayer === thirdLayerKey;
|
const isActive = activeFirstLayer === firstLayerKey && activeSecondLayer === secondLayerKey && activeThirdLayer === thirdLayerKey;
|
||||||
const mergeUrl = `${baseUrl}/${thirdLayerKey}`;
|
const url = itemData ? itemData.path || '' : '';
|
||||||
const url = `/${lang}${baseUrl}/${thirdLayerKey}`;
|
const translation = itemData ? itemData.translation || [] : [];
|
||||||
return (
|
const displayText = translation[2]?.value || thirdLayerKey;
|
||||||
<div key={`${thirdLayerKey}-item`} className="ml-2 my-1">
|
return <div key={`${thirdLayerKey}-item`} className="ml-2 my-1"><ThirdLayerDropdown isActive={isActive} innerText={displayText} url={`${prefix}${url}`} /></div>;
|
||||||
<ThirdLayerDropdown
|
|
||||||
isActive={isActive}
|
|
||||||
innerText={getMenuTranslation(menuTranslationWLang, mergeUrl)}
|
|
||||||
url={url}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderSecondLayerItems = (firstLayerKey: string, secondLayerItems: SecondLayerItems) => {
|
const renderSecondLayerItems = (firstLayerKey: string, secondLayerItems: SecondLayerItems) => {
|
||||||
return Object.entries(secondLayerItems).map(([secondLayerKey, thirdLayerItems]) => {
|
return Object.entries(secondLayerItems).map(([secondLayerKey, thirdLayerItems]) => {
|
||||||
const isActive = activeFirstLayer === firstLayerKey && activeSecondLayer === secondLayerKey;
|
const isActive = activeFirstLayer === firstLayerKey && activeSecondLayer === secondLayerKey;
|
||||||
const isExpanded = expandedSecondLayer === secondLayerKey;
|
const isExpanded = expandedSecondLayer === secondLayerKey;
|
||||||
const mergeUrl = `/${firstLayerKey}/${secondLayerKey}`;
|
const anyThirdLayerItem = Object.values(thirdLayerItems)[0];
|
||||||
|
const translation = anyThirdLayerItem ? anyThirdLayerItem.translation : [];
|
||||||
|
const displayText = translation[1]?.value || secondLayerKey;
|
||||||
return (
|
return (
|
||||||
<div key={`${secondLayerKey}-item`} className="ml-2 my-1">
|
<div key={`${secondLayerKey}-item`} className="ml-2 my-1">
|
||||||
<SecondLayerDropdown
|
<SecondLayerDropdown isActive={isActive} isExpanded={isExpanded} innerText={displayText} onClick={() => handleSecondLayerClick(secondLayerKey)} />
|
||||||
isActive={isActive}
|
{isExpanded && <div className="ml-2 mt-1">{renderThirdLayerItems(firstLayerKey, secondLayerKey, thirdLayerItems)}</div>}
|
||||||
isExpanded={isExpanded}
|
|
||||||
innerText={getMenuTranslation(menuTranslationWLang, mergeUrl)}
|
|
||||||
onClick={() => handleSecondLayerClick(secondLayerKey)}
|
|
||||||
/>
|
|
||||||
{isExpanded && (
|
|
||||||
<div className="ml-2 mt-1">
|
|
||||||
{renderThirdLayerItems(firstLayerKey, secondLayerKey, thirdLayerItems)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderFirstLayerItems = () => {
|
const renderFirstLayerItems = () => {
|
||||||
return Object.entries(menuStructure).map(([firstLayerKey, secondLayerItems]) => {
|
return Object.entries(menuStructure).map(([firstLayerKey, secondLayerItems]) => {
|
||||||
const isActive = activeFirstLayer === firstLayerKey;
|
const isActive = activeFirstLayer === firstLayerKey;
|
||||||
const isExpanded = expandedFirstLayer === firstLayerKey;
|
const isExpanded = expandedFirstLayer === firstLayerKey;
|
||||||
const mergeUrl = `/${firstLayerKey}`;
|
const anySecondLayer = Object.values(secondLayerItems)[0];
|
||||||
|
const anyThirdLayerItem = anySecondLayer ? Object.values(anySecondLayer)[0] : null;
|
||||||
|
const translation = anyThirdLayerItem ? anyThirdLayerItem.translation : [];
|
||||||
|
const displayText = translation[0]?.value || firstLayerKey;
|
||||||
return (
|
return (
|
||||||
<div key={`${firstLayerKey}-item`} className="mb-2">
|
<div key={`${firstLayerKey}-item`} className="mb-2">
|
||||||
<FirstLayerDropdown
|
<FirstLayerDropdown isActive={isActive} isExpanded={isExpanded} innerText={displayText} onClick={() => handleFirstLayerClick(firstLayerKey)} />
|
||||||
isActive={isActive}
|
{isExpanded && <div className="mt-1">{renderSecondLayerItems(firstLayerKey, secondLayerItems)}</div>}
|
||||||
isExpanded={isExpanded}
|
|
||||||
innerText={getMenuTranslation(menuTranslationWLang, mergeUrl)}
|
|
||||||
onClick={() => handleFirstLayerClick(firstLayerKey)}
|
|
||||||
/>
|
|
||||||
{isExpanded && (
|
|
||||||
<div className="mt-1">
|
|
||||||
{renderSecondLayerItems(firstLayerKey, secondLayerItems)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
return <div className="mt-1"><h3 className="text-sm font-semibold mb-1">{menuStaticTranslation[lang as keyof typeof menuStaticTranslation].menu}</h3>{renderFirstLayerItems()}</div>;
|
||||||
return (
|
|
||||||
<div className="mt-1">
|
|
||||||
<h3 className="text-sm font-semibold mb-1">Menu</h3>
|
|
||||||
{renderFirstLayerItems()}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MenuItemsSection;
|
export default MenuItemsSection;
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,7 @@ const UserProfileSection: FC<UserProfileSectionProps> = ({ userData, onlineData
|
||||||
<div className="bg-amber-300 p-2 hover:bg-amber-400 transition-all">
|
<div className="bg-amber-300 p-2 hover:bg-amber-400 transition-all">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="mr-2">
|
<div className="mr-2">
|
||||||
{userData && userData.avatar ? (
|
{userData && userData.avatar ? (<img className="rounded-full border border-white" src={userData.avatar} alt="Avatar" width={40} height={40} />) : (
|
||||||
<img className="rounded-full border border-white" src={userData.avatar} alt="Avatar" width={40} height={40} />
|
|
||||||
) : (
|
|
||||||
<div className="w-10 h-10 rounded-full bg-amber-400 flex items-center justify-center border border-white">
|
<div className="w-10 h-10 rounded-full bg-amber-400 flex items-center justify-center border border-white">
|
||||||
<div className="text-white text-sm font-bold">{userData?.email ? userData.email.slice(0, 2).toUpperCase() : 'U'}</div>
|
<div className="text-white text-sm font-bold">{userData?.email ? userData.email.slice(0, 2).toUpperCase() : 'U'}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,7 @@ async function setContextPageOnline(
|
||||||
body: JSON.stringify(setOnline),
|
body: JSON.stringify(setOnline),
|
||||||
signal: controller.signal,
|
signal: controller.signal,
|
||||||
});
|
});
|
||||||
|
console.log("result", await result.json());
|
||||||
|
|
||||||
// Clear the timeout
|
// Clear the timeout
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,7 @@ import { LanguageTypes } from "@/validations/mutual/language/validations";
|
||||||
import LanguageSelectionItem from "./languageItem";
|
import LanguageSelectionItem from "./languageItem";
|
||||||
|
|
||||||
interface LanguageSelectionComponentProps {
|
interface LanguageSelectionComponentProps {
|
||||||
lang: LanguageTypes;
|
|
||||||
activePage: string;
|
activePage: string;
|
||||||
prefix: string;
|
|
||||||
onlineData: any;
|
onlineData: any;
|
||||||
onlineLoading: boolean;
|
onlineLoading: boolean;
|
||||||
onlineError: any;
|
onlineError: any;
|
||||||
|
|
@ -17,13 +15,14 @@ interface LanguageSelectionComponentProps {
|
||||||
updateOnline: (newOnline: any) => Promise<boolean>;
|
updateOnline: (newOnline: any) => Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LanguageSelectionComponent: React.FC<LanguageSelectionComponentProps> = ({ lang, activePage, prefix, onlineData, onlineLoading, onlineError, refreshOnline, updateOnline }) => {
|
const LanguageSelectionComponent: React.FC<LanguageSelectionComponentProps> = ({ activePage, onlineData, onlineLoading, onlineError, refreshOnline, updateOnline }) => {
|
||||||
|
const lang = onlineData?.lang as LanguageTypes || 'en';
|
||||||
const translations = langGet(lang, languageSelectionTranslation);
|
const translations = langGet(lang, languageSelectionTranslation);
|
||||||
const getPageWithLocale = (locale: LanguageTypes): string => { return `${prefix}/${activePage}` }
|
|
||||||
const languageButtons = [
|
const languageButtons = [
|
||||||
{ activeLang: lang, buttonsLang: "en", refUrl: getPageWithLocale("en"), innerText: langGetKey(translations, "english") },
|
{ activeLang: lang, buttonsLang: "en", refUrl: "en", innerText: langGetKey(translations, "english") },
|
||||||
{ activeLang: lang, buttonsLang: "tr", refUrl: getPageWithLocale("tr"), innerText: langGetKey(translations, "turkish") }
|
{ activeLang: lang, buttonsLang: "tr", refUrl: "tr", innerText: langGetKey(translations, "turkish") }
|
||||||
]
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-end justify-end">
|
<div className="flex items-end justify-end">
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
|
|
@ -32,8 +31,8 @@ const LanguageSelectionComponent: React.FC<LanguageSelectionComponentProps> = ({
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent>
|
<DropdownMenuContent>
|
||||||
{languageButtons.map((props, index) => (
|
{languageButtons.map((props, index) => (
|
||||||
<LanguageSelectionItem key={props.buttonsLang} {...props} onlineData={onlineData}
|
<LanguageSelectionItem key={props.buttonsLang} {...props}
|
||||||
onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline} />
|
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline} />
|
||||||
))}
|
))}
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,176 @@
|
||||||
|
// const menuTranslationEn = {
|
||||||
|
// "/definitions/identifications/people": "People",
|
||||||
|
// "/definitions/identifications/users": "Users",
|
||||||
|
|
||||||
|
// "/definitions/building/parts": "Build Parts",
|
||||||
|
// "/definitions/building/areas": "Building Areas",
|
||||||
|
|
||||||
|
// "/building/accounts/managment/accounts": "Management Accounts",
|
||||||
|
// "/building/accounts/managment/budgets": "Management Budgets",
|
||||||
|
// "/building/accounts/parts/accounts": "Parts Accounts",
|
||||||
|
// "/building/accounts/parts/budgets": "Parts Budgets",
|
||||||
|
|
||||||
|
// "/building/meetings/regular/actions": "Regular Meeting Actions",
|
||||||
|
// "/building/meetings/regular/accounts": "Regular Meeting Accounts",
|
||||||
|
// "/building/meetings/ergunt/actions": "Ergunt Meeting Actions",
|
||||||
|
// "/building/meetings/ergunt/accounts": "Ergunt Meeting Accounts",
|
||||||
|
// "/building/meetings/invited/attendance": "Meeting Invited Attendance",
|
||||||
|
// };
|
||||||
|
|
||||||
const menuTranslationEn = {
|
const menuTranslationEn = {
|
||||||
"/definitions": "Definitions",
|
// New menu
|
||||||
"/definitions/identifications": "Identifications",
|
"/dashboard": [
|
||||||
"/definitions/identifications/people": "People",
|
{ value: "Dashboard", key: "dashboard" },
|
||||||
"/definitions/identifications/users": "Users",
|
{ value: "Dashboard", key: "dashboard" },
|
||||||
|
{ value: "Dashboard", key: "dashboard" },
|
||||||
|
],
|
||||||
|
"/individual": [
|
||||||
|
{ value: "Individual", key: "individual" },
|
||||||
|
{ value: "Individual", key: "individual" },
|
||||||
|
{ value: "Individual", key: "individual" },
|
||||||
|
],
|
||||||
|
"/user": [
|
||||||
|
{ value: "User", key: "user" },
|
||||||
|
{ value: "User", key: "user" },
|
||||||
|
{ value: "User", key: "user" },
|
||||||
|
],
|
||||||
|
"/build": [
|
||||||
|
{ value: "Build", key: "build" },
|
||||||
|
{ value: "Build", key: "build" },
|
||||||
|
{ value: "Build", key: "build" },
|
||||||
|
],
|
||||||
|
"/build/parts": [
|
||||||
|
{ value: "Build", key: "build" },
|
||||||
|
{ value: "Parts", key: "parts" },
|
||||||
|
{ value: "Build", key: "build" },
|
||||||
|
],
|
||||||
|
"/management/budget/actions": [
|
||||||
|
{ value: "Management", key: "management" },
|
||||||
|
{ value: "Budget", key: "budget" },
|
||||||
|
{ value: "Actions", key: "actions" },
|
||||||
|
],
|
||||||
|
"/management/budget": [
|
||||||
|
{ value: "Management", key: "management" },
|
||||||
|
{ value: "Budget", key: "budget" },
|
||||||
|
{ value: "Budget", key: "budget" },
|
||||||
|
],
|
||||||
|
"/annual/meeting/close": [
|
||||||
|
{ value: "Annual", key: "annual" },
|
||||||
|
{ value: "Meeting", key: "meeting" },
|
||||||
|
{ value: "Close", key: "close" },
|
||||||
|
],
|
||||||
|
"/emergency/meeting": [
|
||||||
|
{ value: "Emergency", key: "emergency" },
|
||||||
|
{ value: "Meeting", key: "meeting" },
|
||||||
|
{ value: "Meeting", key: "meeting" },
|
||||||
|
],
|
||||||
|
"/emergency/meeting/close": [
|
||||||
|
{ value: "Emergency", key: "emergency" },
|
||||||
|
{ value: "Meeting", key: "meeting" },
|
||||||
|
{ value: "Close", key: "close" },
|
||||||
|
],
|
||||||
|
"/tenant/accounting": [
|
||||||
|
{ value: "Tenant", key: "tenant" },
|
||||||
|
{ value: "Accounting", key: "accounting" },
|
||||||
|
{ value: "Accounting", key: "accounting" },
|
||||||
|
],
|
||||||
|
"/meeting/participation": [
|
||||||
|
{ value: "Meeting", key: "meeting" },
|
||||||
|
{ value: "Participation", key: "participation" },
|
||||||
|
{ value: "Participation", key: "participation" },
|
||||||
|
],
|
||||||
|
"/tenant/messageToBM": [
|
||||||
|
{ value: "Tenant", key: "tenant" },
|
||||||
|
{ value: "Message To BM", key: "messageToBM" },
|
||||||
|
{ value: "Message To BM", key: "messageToBM" },
|
||||||
|
],
|
||||||
|
"/tenant/messageToOwner": [
|
||||||
|
{ value: "Tenant", key: "tenant" },
|
||||||
|
{ value: "Message To Owner", key: "messageToOwner" },
|
||||||
|
{ value: "Message To Owner", key: "messageToOwner" },
|
||||||
|
],
|
||||||
|
"/management/accounting": [
|
||||||
|
{ value: "Management", key: "management" },
|
||||||
|
{ value: "Accounting", key: "accounting" },
|
||||||
|
{ value: "Accounting", key: "accounting" },
|
||||||
|
],
|
||||||
|
"/build/area": [
|
||||||
|
{ value: "Build", key: "build" },
|
||||||
|
{ value: "Area", key: "area" },
|
||||||
|
{ value: "Area", key: "area" },
|
||||||
|
],
|
||||||
|
"/management/budget/status": [
|
||||||
|
{ value: "Management", key: "management" },
|
||||||
|
{ value: "Budget", key: "budget" },
|
||||||
|
{ value: "Status", key: "status" },
|
||||||
|
],
|
||||||
|
|
||||||
"/definitions/building": "Building",
|
// Early menu
|
||||||
"/definitions/building/parts": "Build Parts",
|
"/definitions/identifications/people": [
|
||||||
"/definitions/building/areas": "Building Areas",
|
{ value: "Definitions", key: "definitions" },
|
||||||
|
{ value: "Identifications", key: "identifications" },
|
||||||
"/building": "Building",
|
{ value: "People", key: "people" },
|
||||||
"/building/accounts": "Account Actions",
|
],
|
||||||
"/building/accounts/managment/accounts": "Management Accounts",
|
"/definitions/identifications/users": [
|
||||||
"/building/accounts/managment/budgets": "Management Budgets",
|
{ value: "Definitions", key: "definitions" },
|
||||||
"/building/accounts/parts/accounts": "Parts Accounts",
|
{ value: "Identifications", key: "identifications" },
|
||||||
"/building/accounts/parts/budgets": "Parts Budgets",
|
{ value: "Users", key: "users" },
|
||||||
|
],
|
||||||
"/building/meetings": "Meetings",
|
"/definitions/building/parts": [
|
||||||
"/building/meetings/regular/actions": "Regular Meeting Actions",
|
{ value: "Definitions", key: "definitions" },
|
||||||
"/building/meetings/regular/accounts": "Regular Meeting Accounts",
|
{ value: "Building", key: "building" },
|
||||||
"/building/meetings/ergunt/actions": "Ergunt Meeting Actions",
|
{ value: "Parts", key: "parts" },
|
||||||
"/building/meetings/ergunt/accounts": "Ergunt Meeting Accounts",
|
],
|
||||||
"/building/meetings/invited/attendance": "Meeting Invited Attendance",
|
"/definitions/building/areas": [
|
||||||
|
{ value: "Definitions", key: "definitions" },
|
||||||
|
{ value: "Building", key: "building" },
|
||||||
|
{ value: "Areas", key: "areas" },
|
||||||
|
],
|
||||||
|
"/building/accounts/managment/accounts": [
|
||||||
|
{ value: "Building", key: "building" },
|
||||||
|
{ value: "Accounts", key: "accounts" },
|
||||||
|
{ value: "Managment", key: "managment" },
|
||||||
|
],
|
||||||
|
"/building/accounts/managment/budgets": [
|
||||||
|
{ value: "Building", key: "building" },
|
||||||
|
{ value: "Accounts", key: "accounts" },
|
||||||
|
{ value: "Managment", key: "managment" },
|
||||||
|
],
|
||||||
|
"/building/accounts/parts/accounts": [
|
||||||
|
{ value: "Building", key: "building" },
|
||||||
|
{ value: "Accounts", key: "accounts" },
|
||||||
|
{ value: "Parts", key: "parts" },
|
||||||
|
],
|
||||||
|
"/building/accounts/parts/budgets": [
|
||||||
|
{ value: "Building", key: "building" },
|
||||||
|
{ value: "Accounts", key: "accounts" },
|
||||||
|
{ value: "Parts", key: "parts" },
|
||||||
|
],
|
||||||
|
"/building/meetings/regular/actions": [
|
||||||
|
{ value: "Building", key: "building" },
|
||||||
|
{ value: "Meetings", key: "meetings" },
|
||||||
|
{ value: "Regular", key: "regular" },
|
||||||
|
],
|
||||||
|
"/building/meetings/regular/accounts": [
|
||||||
|
{ value: "Building", key: "building" },
|
||||||
|
{ value: "Meetings", key: "meetings" },
|
||||||
|
{ value: "Regular", key: "regular" },
|
||||||
|
],
|
||||||
|
"/building/meetings/ergunt/actions": [
|
||||||
|
{ value: "Building", key: "building" },
|
||||||
|
{ value: "Meetings", key: "meetings" },
|
||||||
|
{ value: "Ergunt", key: "ergunt" },
|
||||||
|
],
|
||||||
|
"/building/meetings/ergunt/accounts": [
|
||||||
|
{ value: "Building", key: "building" },
|
||||||
|
{ value: "Meetings", key: "meetings" },
|
||||||
|
{ value: "Ergunt", key: "ergunt" },
|
||||||
|
],
|
||||||
|
"/building/meetings/invited/attendance": [
|
||||||
|
{ value: "Building", key: "building" },
|
||||||
|
{ value: "Meetings", key: "meetings" },
|
||||||
|
{ value: "Invited", key: "invited" },
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export { menuTranslationEn };
|
export { menuTranslationEn };
|
||||||
// export { menuTranslationEn, menuIndex };
|
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,176 @@
|
||||||
|
// const menuTranslationTr = {
|
||||||
|
// "/definitions/identifications/people": "Kişiler",
|
||||||
|
// "/definitions/identifications/users": "Kullanıcılar",
|
||||||
|
|
||||||
|
// "/definitions/building/parts": "Daireler",
|
||||||
|
// "/definitions/building/areas": "Bina Alanları",
|
||||||
|
|
||||||
|
// "/building/accounts/managment/accounts": "Bina Hesapları",
|
||||||
|
// "/building/accounts/managment/budgets": "Bina Bütçesi",
|
||||||
|
// "/building/accounts/parts/accounts": "Daire Hesapları",
|
||||||
|
// "/building/accounts/parts/budgets": "Daire Bütçesi",
|
||||||
|
|
||||||
|
// "/building/meetings/regular/actions": "Düzenli Toplantı Eylemleri",
|
||||||
|
// "/building/meetings/regular/accounts": "Düzenli Toplantı Accounts",
|
||||||
|
// "/building/meetings/ergunt/actions": "Ergunt Toplantı Eylemleri",
|
||||||
|
// "/building/meetings/ergunt/accounts": "Ergunt Toplantı Accounts",
|
||||||
|
// "/building/meetings/invited/attendance": "Toplantı Davetli Katılımlar",
|
||||||
|
// };
|
||||||
|
|
||||||
const menuTranslationTr = {
|
const menuTranslationTr = {
|
||||||
"/definitions": "Tanımlamalar",
|
// New menu
|
||||||
"/definitions/identifications": "Tanımlamalar",
|
"/dashboard": [
|
||||||
"/definitions/identifications/people": "Kişiler",
|
{ value: "Dashboard", key: "dashboard" },
|
||||||
"/definitions/identifications/users": "Kullanıcılar",
|
{ value: "Dashboard", key: "dashboard" },
|
||||||
|
{ value: "Dashboard", key: "dashboard" },
|
||||||
|
],
|
||||||
|
"/individual": [
|
||||||
|
{ value: "Individual", key: "individual" },
|
||||||
|
{ value: "Individual", key: "individual" },
|
||||||
|
{ value: "Individual", key: "individual" },
|
||||||
|
],
|
||||||
|
"/user": [
|
||||||
|
{ value: "User", key: "user" },
|
||||||
|
{ value: "User", key: "user" },
|
||||||
|
{ value: "User", key: "user" },
|
||||||
|
],
|
||||||
|
"/build": [
|
||||||
|
{ value: "Build", key: "build" },
|
||||||
|
{ value: "Build", key: "build" },
|
||||||
|
{ value: "Build", key: "build" },
|
||||||
|
],
|
||||||
|
"/build/parts": [
|
||||||
|
{ value: "Build", key: "build" },
|
||||||
|
{ value: "Parts", key: "parts" },
|
||||||
|
{ value: "Build", key: "build" },
|
||||||
|
],
|
||||||
|
"/management/budget/actions": [
|
||||||
|
{ value: "Management", key: "management" },
|
||||||
|
{ value: "Budget", key: "budget" },
|
||||||
|
{ value: "Actions", key: "actions" },
|
||||||
|
],
|
||||||
|
"/management/budget": [
|
||||||
|
{ value: "Management", key: "management" },
|
||||||
|
{ value: "Budget", key: "budget" },
|
||||||
|
{ value: "Budget", key: "budget" },
|
||||||
|
],
|
||||||
|
"/annual/meeting/close": [
|
||||||
|
{ value: "Annual", key: "annual" },
|
||||||
|
{ value: "Meeting", key: "meeting" },
|
||||||
|
{ value: "Close", key: "close" },
|
||||||
|
],
|
||||||
|
"/emergency/meeting": [
|
||||||
|
{ value: "Emergency", key: "emergency" },
|
||||||
|
{ value: "Meeting", key: "meeting" },
|
||||||
|
{ value: "Meeting", key: "meeting" },
|
||||||
|
],
|
||||||
|
"/emergency/meeting/close": [
|
||||||
|
{ value: "Emergency", key: "emergency" },
|
||||||
|
{ value: "Meeting", key: "meeting" },
|
||||||
|
{ value: "Close", key: "close" },
|
||||||
|
],
|
||||||
|
"/tenant/accounting": [
|
||||||
|
{ value: "Tenant", key: "tenant" },
|
||||||
|
{ value: "Accounting", key: "accounting" },
|
||||||
|
{ value: "Accounting", key: "accounting" },
|
||||||
|
],
|
||||||
|
"/meeting/participation": [
|
||||||
|
{ value: "Meeting", key: "meeting" },
|
||||||
|
{ value: "Participation", key: "participation" },
|
||||||
|
{ value: "Participation", key: "participation" },
|
||||||
|
],
|
||||||
|
"/tenant/messageToBM": [
|
||||||
|
{ value: "Tenant", key: "tenant" },
|
||||||
|
{ value: "Message To BM", key: "messageToBM" },
|
||||||
|
{ value: "Message To BM", key: "messageToBM" },
|
||||||
|
],
|
||||||
|
"/tenant/messageToOwner": [
|
||||||
|
{ value: "Tenant", key: "tenant" },
|
||||||
|
{ value: "Message To Owner", key: "messageToOwner" },
|
||||||
|
{ value: "Message To Owner", key: "messageToOwner" },
|
||||||
|
],
|
||||||
|
"/management/accounting": [
|
||||||
|
{ value: "Management", key: "management" },
|
||||||
|
{ value: "Accounting", key: "accounting" },
|
||||||
|
{ value: "Accounting", key: "accounting" },
|
||||||
|
],
|
||||||
|
"/build/area": [
|
||||||
|
{ value: "Build", key: "build" },
|
||||||
|
{ value: "Area", key: "area" },
|
||||||
|
{ value: "Area", key: "area" },
|
||||||
|
],
|
||||||
|
"/management/budget/status": [
|
||||||
|
{ value: "Management", key: "management" },
|
||||||
|
{ value: "Budget", key: "budget" },
|
||||||
|
{ value: "Status", key: "status" },
|
||||||
|
],
|
||||||
|
|
||||||
"/definitions/building": "Bina",
|
// Early menu
|
||||||
"/definitions/building/parts": "Daireler",
|
"/definitions/identifications/people": [
|
||||||
"/definitions/building/areas": "Bina Alanları",
|
{ value: "Tanımlamalar", key: "definitions" },
|
||||||
|
{ value: "Tanımlamalar", key: "identifications" },
|
||||||
"/building": "Bina",
|
{ value: "Kişiler", key: "people" },
|
||||||
"/building/accounts": "Account Eylemleri",
|
],
|
||||||
"/building/accounts/managment/accounts": "Bina Hesapları",
|
"/definitions/identifications/users": [
|
||||||
"/building/accounts/managment/budgets": "Bina Bütçesi",
|
{ value: "Tanımlamalar", key: "definitions" },
|
||||||
"/building/accounts/parts/accounts": "Daire Hesapları",
|
{ value: "Tanımlamalar", key: "identifications" },
|
||||||
"/building/accounts/parts/budgets": "Daire Bütçesi",
|
{ value: "Kullanıcılar", key: "users" },
|
||||||
|
],
|
||||||
"/building/meetings": "Toplantılar",
|
"/definitions/building/parts": [
|
||||||
"/building/meetings/regular/actions": "Düzenli Toplantı Eylemleri",
|
{ value: "Tanımlamalar", key: "definitions" },
|
||||||
"/building/meetings/regular/accounts": "Düzenli Toplantı Accounts",
|
{ value: "Bina", key: "building" },
|
||||||
"/building/meetings/ergunt/actions": "Ergunt Toplantı Eylemleri",
|
{ value: "Daireler", key: "parts" },
|
||||||
"/building/meetings/ergunt/accounts": "Ergunt Toplantı Accounts",
|
],
|
||||||
"/building/meetings/invited/attendance": "Toplantı Davetli Katılımlar",
|
"/definitions/building/areas": [
|
||||||
|
{ value: "Tanımlamalar", key: "definitions" },
|
||||||
|
{ value: "Bina", key: "building" },
|
||||||
|
{ value: "Bina Alanları", key: "areas" },
|
||||||
|
],
|
||||||
|
"/building/accounts/managment/accounts": [
|
||||||
|
{ value: "Bina", key: "building" },
|
||||||
|
{ value: "Hesap Eylemleri", key: "accounts" },
|
||||||
|
{ value: "Yönetim", key: "managment" },
|
||||||
|
],
|
||||||
|
"/building/accounts/managment/budgets": [
|
||||||
|
{ value: "Bina", key: "building" },
|
||||||
|
{ value: "Hesap Eylemleri", key: "accounts" },
|
||||||
|
{ value: "Yönetim", key: "managment" },
|
||||||
|
],
|
||||||
|
"/building/accounts/parts/accounts": [
|
||||||
|
{ value: "Bina", key: "building" },
|
||||||
|
{ value: "Hesap Eylemleri", key: "accounts" },
|
||||||
|
{ value: "Daireler", key: "parts" },
|
||||||
|
],
|
||||||
|
"/building/accounts/parts/budgets": [
|
||||||
|
{ value: "Bina", key: "building" },
|
||||||
|
{ value: "Hesap Eylemleri", key: "accounts" },
|
||||||
|
{ value: "Daireler", key: "parts" },
|
||||||
|
],
|
||||||
|
"/building/meetings/regular/actions": [
|
||||||
|
{ value: "Bina", key: "building" },
|
||||||
|
{ value: "Toplantılar", key: "meetings" },
|
||||||
|
{ value: "Düzenli", key: "regular" },
|
||||||
|
],
|
||||||
|
"/building/meetings/regular/accounts": [
|
||||||
|
{ value: "Bina", key: "building" },
|
||||||
|
{ value: "Toplantılar", key: "meetings" },
|
||||||
|
{ value: "Düzenli", key: "regular" },
|
||||||
|
],
|
||||||
|
"/building/meetings/ergunt/actions": [
|
||||||
|
{ value: "Bina", key: "building" },
|
||||||
|
{ value: "Toplantılar", key: "meetings" },
|
||||||
|
{ value: "Acil", key: "ergunt" },
|
||||||
|
],
|
||||||
|
"/building/meetings/ergunt/accounts": [
|
||||||
|
{ value: "Bina", key: "building" },
|
||||||
|
{ value: "Toplantılar", key: "meetings" },
|
||||||
|
{ value: "Acil", key: "ergunt" },
|
||||||
|
],
|
||||||
|
"/building/meetings/invited/attendance": [
|
||||||
|
{ value: "Bina", key: "building" },
|
||||||
|
{ value: "Toplantılar", key: "meetings" },
|
||||||
|
{ value: "Davetli", key: "invited" },
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export { menuTranslationTr };
|
export { menuTranslationTr };
|
||||||
|
|
|
||||||
|
|
@ -1,68 +1,48 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
import React, { FC } from 'react';
|
||||||
import HeaderComponent from "@/components/custom/header/component";
|
|
||||||
import MenuComponent from "@/components/custom/menu/component";
|
|
||||||
import ContentComponent from "@/components/custom/content/component";
|
|
||||||
import FooterComponent from "@/components/custom/footer/component";
|
|
||||||
import React, { FC, useEffect } from 'react';
|
|
||||||
import { ClientProviders } from "@/components/mutual/providers/client-providers";
|
import { ClientProviders } from "@/components/mutual/providers/client-providers";
|
||||||
import { ClientOnline, ClientMenu, ClientSelection, ClientUser, ClientSettings } from "@/types/mutual/context/validations";
|
|
||||||
import { ModeTypes } from "@/validations/mutual/dashboard/props";
|
import { ModeTypes } from "@/validations/mutual/dashboard/props";
|
||||||
import type { LanguageTypes } from "@/validations/mutual/language/validations";
|
|
||||||
|
|
||||||
// Import all context hooks
|
|
||||||
import { useMenu } from "@/components/mutual/context/menu/context";
|
import { useMenu } from "@/components/mutual/context/menu/context";
|
||||||
import { useOnline } from "@/components/mutual/context/online/context";
|
import { useOnline } from "@/components/mutual/context/online/context";
|
||||||
import { useSelection } from "@/components/mutual/context/selection/context";
|
import { useSelection } from "@/components/mutual/context/selection/context";
|
||||||
import { useUser } from "@/components/mutual/context/user/context";
|
import { useUser } from "@/components/mutual/context/user/context";
|
||||||
import { useConfig } from "@/components/mutual/context/config/context";
|
import { useConfig } from "@/components/mutual/context/config/context";
|
||||||
|
|
||||||
interface ClientLayoutProps {
|
import HeaderComponent from "@/components/custom/header/component";
|
||||||
allProps: {
|
import MenuComponent from "@/components/custom/menu/component";
|
||||||
lang: LanguageTypes;
|
import ContentComponent from "@/components/custom/content/component";
|
||||||
activePageUrl: string;
|
import FooterComponent from "@/components/custom/footer/component";
|
||||||
mode: ModeTypes;
|
|
||||||
prefix: string;
|
interface ClientLayoutProps { activePageUrl: string, searchParams: Record<string, any> }
|
||||||
};
|
|
||||||
packs?: {
|
const ClientLayout: FC<ClientLayoutProps> = ({ activePageUrl, searchParams }) => {
|
||||||
menu?: ClientMenu;
|
|
||||||
selection?: ClientSelection;
|
|
||||||
user?: ClientUser;
|
|
||||||
settings?: ClientSettings;
|
|
||||||
online?: ClientOnline;
|
|
||||||
};
|
|
||||||
useReloadWindow?: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ClientLayout: FC<ClientLayoutProps> = ({ allProps }) => {
|
|
||||||
const { onlineData, isLoading: onlineLoading, error: onlineError, refreshOnline, updateOnline } = useOnline();
|
const { onlineData, isLoading: onlineLoading, error: onlineError, refreshOnline, updateOnline } = useOnline();
|
||||||
const { userData, isLoading: userLoading, error: userError } = useUser();
|
const { userData, isLoading: userLoading, error: userError, refreshUser, updateUser } = useUser();
|
||||||
const { availableApplications, isLoading: menuLoading, error: menuError, menuData, refreshMenu } = useMenu();
|
const { availableApplications, isLoading: menuLoading, error: menuError, menuData, refreshMenu, updateMenu } = useMenu();
|
||||||
const { selectionData, isLoading: selectionLoading, error: selectionError } = useSelection();
|
const { selectionData, isLoading: selectionLoading, error: selectionError, refreshSelection, updateSelection } = useSelection();
|
||||||
const { configData, isLoading: configLoading, error: configError } = useConfig();
|
const { configData, isLoading: configLoading, error: configError, refreshConfig, updateConfig } = useConfig();
|
||||||
|
const prefix = "/panel"
|
||||||
|
const mode = (searchParams?.mode as ModeTypes) || 'shortList';
|
||||||
|
console.log("onlineData", onlineData)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ClientProviders>
|
<ClientProviders>
|
||||||
<div className="flex flex-col min-w-screen">
|
<div className="flex flex-col min-w-screen">
|
||||||
<HeaderComponent {...allProps}
|
<HeaderComponent activePageUrl={activePageUrl} searchParams={searchParams}
|
||||||
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError}
|
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline}
|
||||||
refreshOnline={refreshOnline} updateOnline={updateOnline}
|
userData={userData} userLoading={userLoading} userError={userError} refreshUser={refreshUser} updateUser={updateUser} />
|
||||||
userData={userData} userLoading={userLoading} userError={userError}
|
<MenuComponent availableApplications={availableApplications} activePageUrl={activePageUrl} prefix={prefix} searchParams={searchParams}
|
||||||
/>
|
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline}
|
||||||
<MenuComponent {...allProps}
|
userData={userData} userLoading={userLoading} userError={userError} refreshUser={refreshUser} updateUser={updateUser}
|
||||||
availableApplications={availableApplications}
|
selectionData={selectionData} selectionLoading={selectionLoading} selectionError={selectionError} refreshSelection={refreshSelection} updateSelection={updateSelection}
|
||||||
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError}
|
menuData={menuData} menuLoading={menuLoading} menuError={menuError} refreshMenu={refreshMenu} updateMenu={updateMenu} />
|
||||||
userData={userData} userLoading={userLoading} userError={userError}
|
<ContentComponent activePageUrl={activePageUrl} mode={mode} searchParams={searchParams}
|
||||||
selectionData={selectionData} selectionLoading={selectionLoading} selectionError={selectionError}
|
userData={userData} userLoading={userLoading} userError={userError} refreshUser={refreshUser} updateUser={updateUser}
|
||||||
menuData={menuData} menuLoading={menuLoading} menuError={menuError} />
|
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline} />
|
||||||
<ContentComponent {...allProps}
|
<FooterComponent activePageUrl={activePageUrl} searchParams={searchParams}
|
||||||
userData={userData} userLoading={userLoading} userError={userError}
|
configData={configData} configLoading={configLoading} configError={configError} refreshConfig={refreshConfig} updateConfig={updateConfig}
|
||||||
selectionData={selectionData} selectionLoading={selectionLoading} selectionError={selectionError}
|
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline} />
|
||||||
/>
|
|
||||||
<FooterComponent {...allProps}
|
|
||||||
availableApplications={availableApplications}
|
|
||||||
configData={configData} configLoading={configLoading} configError={configError}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</ClientProviders>
|
</ClientProviders>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,10 @@
|
||||||
'use server';
|
'use server';
|
||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { DashboardLayoutProps, ModeTypes } from "@/validations/mutual/dashboard/props";
|
import { DashboardLayoutProps } from "@/validations/mutual/dashboard/props";
|
||||||
import { ClientLayout } from "./client";
|
import { ClientLayout } from "./client";
|
||||||
|
|
||||||
const DashboardLayout: FC<DashboardLayoutProps> = async ({ params, searchParams, lang }) => {
|
const DashboardLayout: FC<DashboardLayoutProps> = async ({ params, searchParams }) => {
|
||||||
const mode = (searchParams?.mode as ModeTypes) || 'shortList';
|
const activePageUrl = `/${params.page?.join('/')}`; return <ClientLayout activePageUrl={activePageUrl} searchParams={searchParams} />
|
||||||
const activePageUrl = `/${params.page?.join('/')}`;
|
|
||||||
const allProps = { lang: lang || '', activePageUrl, mode, prefix: "/panel" };
|
|
||||||
return <ClientLayout allProps={allProps} />
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export { DashboardLayout };
|
export { DashboardLayout };
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,85 @@
|
||||||
import { ContentProps } from "@/validations/mutual/dashboard/props";
|
import { ContentProps } from "@/validations/mutual/dashboard/props";
|
||||||
import superUserBuildingPartsTenantSomething from "./building/parts/tenantSomething/page";
|
import superUserBuildingPartsTenantSomething from "./building/parts/tenantSomething/page";
|
||||||
|
|
||||||
|
function getPageComponent(
|
||||||
|
baseUrl: string,
|
||||||
|
pageKey: string
|
||||||
|
): React.FC<ContentProps> | null {
|
||||||
|
const pageGroup = pageIndexMulti[baseUrl];
|
||||||
|
if (!pageGroup) {
|
||||||
|
console.log(`No page group found for URL: ${baseUrl}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PageComponent = pageGroup[pageKey];
|
||||||
|
if (!PageComponent) {
|
||||||
|
console.log(
|
||||||
|
`No page component found for key: ${pageKey} in URL group: ${baseUrl}`
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PageComponent;
|
||||||
|
}
|
||||||
|
|
||||||
const pageIndexMulti: Record<string, Record<string, React.FC<ContentProps>>> = {
|
const pageIndexMulti: Record<string, Record<string, React.FC<ContentProps>>> = {
|
||||||
"/main/pages/user/dashboard": { superUserBuildingPartsTenantSomething },
|
// New pages
|
||||||
|
"/dashboard": {
|
||||||
|
superUserBuildingPartsTenantSomething,
|
||||||
|
},
|
||||||
|
"/individual": {
|
||||||
|
superUserBuildingPartsTenantSomething,
|
||||||
|
},
|
||||||
|
"/user": {
|
||||||
|
superUserBuildingPartsTenantSomething,
|
||||||
|
},
|
||||||
|
"/build": {
|
||||||
|
superUserBuildingPartsTenantSomething,
|
||||||
|
},
|
||||||
|
"/build/parts": {
|
||||||
|
superUserBuildingPartsTenantSomething,
|
||||||
|
},
|
||||||
|
"/management/budget/actions": {
|
||||||
|
superUserBuildingPartsTenantSomething,
|
||||||
|
},
|
||||||
|
"/management/budget": {
|
||||||
|
superUserBuildingPartsTenantSomething,
|
||||||
|
},
|
||||||
|
"/annual/meeting/close": {
|
||||||
|
superUserBuildingPartsTenantSomething,
|
||||||
|
},
|
||||||
|
"/emergency/meeting": {
|
||||||
|
superUserBuildingPartsTenantSomething,
|
||||||
|
},
|
||||||
|
"/emergency/meeting/close": {
|
||||||
|
superUserBuildingPartsTenantSomething,
|
||||||
|
},
|
||||||
|
"/tenant/accounting": {
|
||||||
|
superUserBuildingPartsTenantSomething,
|
||||||
|
},
|
||||||
|
"/meeting/participation": {
|
||||||
|
superUserBuildingPartsTenantSomething,
|
||||||
|
},
|
||||||
|
"/tenant/messageToBM": {
|
||||||
|
superUserBuildingPartsTenantSomething,
|
||||||
|
},
|
||||||
|
"/tenant/messageToOwner": {
|
||||||
|
superUserBuildingPartsTenantSomething,
|
||||||
|
},
|
||||||
|
"/management/accounting": {
|
||||||
|
superUserBuildingPartsTenantSomething,
|
||||||
|
},
|
||||||
|
"/build/area": {
|
||||||
|
superUserBuildingPartsTenantSomething,
|
||||||
|
},
|
||||||
|
"/management/budget/status": {
|
||||||
|
superUserBuildingPartsTenantSomething,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Early pages
|
||||||
|
"/main/pages/user/dashboard": {
|
||||||
|
superUserBuildingPartsTenantSomething,
|
||||||
|
},
|
||||||
"/definitions/identifications/people": {
|
"/definitions/identifications/people": {
|
||||||
superUserBuildingPartsTenantSomething,
|
superUserBuildingPartsTenantSomething,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import pageIndexMulti from "@/pages/multi/index";
|
||||||
import pageIndexSingle from "@/pages/single/index";
|
import pageIndexSingle from "@/pages/single/index";
|
||||||
import ContentToRenderNoPage from "@/pages/mutual/noContent/page";
|
import ContentToRenderNoPage from "@/pages/mutual/noContent/page";
|
||||||
|
|
||||||
async function resolveWhichPageToRenderSingle({ activePageUrl }: ResolverProps): Promise<React.FC<ContentProps> | null> {
|
async function resolveWhichPageToRenderSingle({ activePageUrl }: ResolverProps): Promise<React.FC<ContentProps> | React.FC<{ lang: string }> | null> {
|
||||||
try {
|
try {
|
||||||
return `${activePageUrl}` in pageIndexSingle ? pageIndexSingle[`${activePageUrl}`] : ContentToRenderNoPage
|
return `${activePageUrl}` in pageIndexSingle ? pageIndexSingle[`${activePageUrl}`] : ContentToRenderNoPage
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -16,7 +16,7 @@ async function resolveWhichPageToRenderSingle({ activePageUrl }: ResolverProps):
|
||||||
return ContentToRenderNoPage
|
return ContentToRenderNoPage
|
||||||
}
|
}
|
||||||
|
|
||||||
async function resolveWhichPageToRenderMulti({ activePageUrl }: ResolverProps): Promise<React.FC<ContentProps> | null> {
|
async function resolveWhichPageToRenderMulti({ activePageUrl }: ResolverProps): Promise<React.FC<ContentProps> | React.FC<{ lang: string }> | null> {
|
||||||
const pageToRender = await retrievePageToRender(activePageUrl) // TODO: Retrieve page to render
|
const pageToRender = await retrievePageToRender(activePageUrl) // TODO: Retrieve page to render
|
||||||
try {
|
try {
|
||||||
const ApplicationToRender = pageIndexMulti[activePageUrl][pageToRender]
|
const ApplicationToRender = pageIndexMulti[activePageUrl][pageToRender]
|
||||||
|
|
|
||||||
|
|
@ -16,49 +16,9 @@ type ModeTypes = "shortList" | "fullList" | "create" | "update" | "view";
|
||||||
const ModeTypesList = ["shortList", "fullList", "create", "update", "view"];
|
const ModeTypesList = ["shortList", "fullList", "create", "update", "view"];
|
||||||
|
|
||||||
interface ContentProps {
|
interface ContentProps {
|
||||||
lang: LanguageTypes;
|
|
||||||
activePageUrl: string;
|
activePageUrl: string;
|
||||||
mode?: ModeTypes;
|
mode?: ModeTypes;
|
||||||
userData: any;
|
searchParams: Record<string, any>;
|
||||||
userLoading: boolean;
|
|
||||||
userError: any;
|
|
||||||
selectionData: any;
|
|
||||||
selectionLoading: boolean;
|
|
||||||
selectionError: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface MenuProps {
|
|
||||||
lang: LanguageTypes;
|
|
||||||
availableApplications: string[];
|
|
||||||
activePageUrl: string;
|
|
||||||
onlineData: any;
|
|
||||||
onlineLoading: boolean;
|
|
||||||
onlineError: any;
|
|
||||||
userData: any;
|
|
||||||
userLoading: boolean;
|
|
||||||
userError: any;
|
|
||||||
selectionData: any;
|
|
||||||
selectionLoading: boolean;
|
|
||||||
selectionError: any;
|
|
||||||
menuData: any;
|
|
||||||
menuLoading: boolean;
|
|
||||||
menuError: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FooterProps {
|
|
||||||
lang: LanguageTypes;
|
|
||||||
availableApplications: string[];
|
|
||||||
activePageUrl: string;
|
|
||||||
configData: any;
|
|
||||||
configLoading: boolean;
|
|
||||||
configError: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface HeaderProps {
|
|
||||||
lang: LanguageTypes;
|
|
||||||
activePageUrl: string;
|
|
||||||
prefix: string;
|
|
||||||
mode?: ModeTypes;
|
|
||||||
onlineData: any;
|
onlineData: any;
|
||||||
onlineLoading: boolean;
|
onlineLoading: boolean;
|
||||||
onlineError: any;
|
onlineError: any;
|
||||||
|
|
@ -67,6 +27,65 @@ interface HeaderProps {
|
||||||
userData: any;
|
userData: any;
|
||||||
userLoading: boolean;
|
userLoading: boolean;
|
||||||
userError: any;
|
userError: any;
|
||||||
|
refreshUser: () => Promise<void>;
|
||||||
|
updateUser: (newUser: any) => Promise<boolean>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MenuProps {
|
||||||
|
availableApplications: string[];
|
||||||
|
searchParams: Record<string, any>;
|
||||||
|
activePageUrl: string;
|
||||||
|
prefix?: string;
|
||||||
|
onlineData: any;
|
||||||
|
onlineLoading: boolean;
|
||||||
|
onlineError: any;
|
||||||
|
refreshOnline: () => Promise<void>;
|
||||||
|
updateOnline: (newOnline: any) => Promise<boolean>;
|
||||||
|
userData: any;
|
||||||
|
userLoading: boolean;
|
||||||
|
userError: any;
|
||||||
|
refreshUser: () => Promise<void>;
|
||||||
|
updateUser: (newUser: any) => Promise<boolean>;
|
||||||
|
selectionData: any;
|
||||||
|
selectionLoading: boolean;
|
||||||
|
selectionError: any;
|
||||||
|
refreshSelection: () => Promise<void>;
|
||||||
|
updateSelection: (newSelection: any) => Promise<boolean>;
|
||||||
|
menuData: any;
|
||||||
|
menuLoading: boolean;
|
||||||
|
menuError: any;
|
||||||
|
refreshMenu: () => Promise<void>;
|
||||||
|
updateMenu: (newMenu: any) => Promise<boolean>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FooterProps {
|
||||||
|
searchParams: Record<string, any>;
|
||||||
|
activePageUrl: string;
|
||||||
|
configData: any;
|
||||||
|
configLoading: boolean;
|
||||||
|
configError: any;
|
||||||
|
refreshConfig: () => Promise<void>;
|
||||||
|
updateConfig: (newConfig: any) => Promise<boolean>;
|
||||||
|
onlineData: any;
|
||||||
|
onlineLoading: boolean;
|
||||||
|
onlineError: any;
|
||||||
|
refreshOnline: () => Promise<void>;
|
||||||
|
updateOnline: (newOnline: any) => Promise<boolean>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HeaderProps {
|
||||||
|
activePageUrl: string;
|
||||||
|
searchParams: Record<string, any>;
|
||||||
|
onlineData: any;
|
||||||
|
onlineLoading: boolean;
|
||||||
|
onlineError: any;
|
||||||
|
refreshOnline: () => Promise<void>;
|
||||||
|
updateOnline: (newOnline: any) => Promise<boolean>;
|
||||||
|
userData: any;
|
||||||
|
userLoading: boolean;
|
||||||
|
userError: any;
|
||||||
|
refreshUser: () => Promise<void>;
|
||||||
|
updateUser: (newUser: any) => Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type {
|
export type {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue