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
|
||||
# mem_limit: 2048m
|
||||
|
||||
account_service:
|
||||
container_name: account_service
|
||||
build:
|
||||
context: .
|
||||
dockerfile: api_services/api_builds/account_service/Dockerfile
|
||||
env_file:
|
||||
- api_env.env
|
||||
networks:
|
||||
- wag-services
|
||||
environment:
|
||||
- API_PATH=app:app
|
||||
- API_HOST=0.0.0.0
|
||||
- API_PORT=8004
|
||||
- API_LOG_LEVEL=info
|
||||
- API_RELOAD=1
|
||||
- API_APP_NAME=evyos-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_APP_URL=https://account_service
|
||||
ports:
|
||||
- "8004:8004"
|
||||
# account_service:
|
||||
# container_name: account_service
|
||||
# build:
|
||||
# context: .
|
||||
# dockerfile: api_services/api_builds/account_service/Dockerfile
|
||||
# env_file:
|
||||
# - api_env.env
|
||||
# networks:
|
||||
# - wag-services
|
||||
# environment:
|
||||
# - API_PATH=app:app
|
||||
# - API_HOST=0.0.0.0
|
||||
# - API_PORT=8004
|
||||
# - API_LOG_LEVEL=info
|
||||
# - API_RELOAD=1
|
||||
# - API_APP_NAME=evyos-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_APP_URL=https://account_service
|
||||
# ports:
|
||||
# - "8004:8004"
|
||||
|
||||
building_service:
|
||||
container_name: building_service
|
||||
build:
|
||||
context: .
|
||||
dockerfile: api_services/api_builds/building_service/Dockerfile
|
||||
env_file:
|
||||
- api_env.env
|
||||
networks:
|
||||
- wag-services
|
||||
environment:
|
||||
- API_PATH=app:app
|
||||
- API_HOST=0.0.0.0
|
||||
- API_PORT=8006
|
||||
- API_LOG_LEVEL=info
|
||||
- API_RELOAD=1
|
||||
- API_APP_NAME=evyos-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_APP_URL=https://building_service
|
||||
ports:
|
||||
- "8006:8006"
|
||||
# building_service:
|
||||
# container_name: building_service
|
||||
# build:
|
||||
# context: .
|
||||
# dockerfile: api_services/api_builds/building_service/Dockerfile
|
||||
# env_file:
|
||||
# - api_env.env
|
||||
# networks:
|
||||
# - wag-services
|
||||
# environment:
|
||||
# - API_PATH=app:app
|
||||
# - API_HOST=0.0.0.0
|
||||
# - API_PORT=8006
|
||||
# - API_LOG_LEVEL=info
|
||||
# - API_RELOAD=1
|
||||
# - API_APP_NAME=evyos-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_APP_URL=https://building_service
|
||||
# ports:
|
||||
# - "8006:8006"
|
||||
|
||||
identity_service:
|
||||
container_name: identity_service
|
||||
|
|
|
|||
|
|
@ -9,11 +9,7 @@ const MainEnPage: React.FC<MaindasboardPageProps> = async ({ params, searchParam
|
|||
const searchParameters = await searchParams;
|
||||
const tokenValid = await checkAccessTokenIsValid()
|
||||
if (!tokenValid) { redirect("/auth/login") }
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<DashboardLayout params={parameters} searchParams={searchParameters} lang="en" />
|
||||
</div>
|
||||
);
|
||||
return <div className="flex flex-col items-center justify-center"><DashboardLayout params={parameters} searchParams={searchParameters} lang="en" /></div>
|
||||
}
|
||||
|
||||
export default MainEnPage;
|
||||
|
|
|
|||
|
|
@ -3,33 +3,28 @@ import ContentToRenderNoPage from "@/pages/mutual/noContent/page";
|
|||
import pageIndexMulti from "@/pages/multi/index";
|
||||
|
||||
const PageToBeChildrendMulti: React.FC<ContentProps> = ({
|
||||
lang,
|
||||
activePageUrl,
|
||||
mode,
|
||||
userData,
|
||||
userLoading,
|
||||
userError,
|
||||
selectionData,
|
||||
selectionLoading,
|
||||
selectionError,
|
||||
useReloadWindow
|
||||
onlineData,
|
||||
onlineLoading,
|
||||
onlineError,
|
||||
searchParams,
|
||||
refreshOnline,
|
||||
updateOnline,
|
||||
refreshUser,
|
||||
updateUser,
|
||||
}) => {
|
||||
const pageComponents = pageIndexMulti[activePageUrl];
|
||||
if (!pageComponents) { return <ContentToRenderNoPage lang={lang} /> }
|
||||
if (!pageComponents) { return <ContentToRenderNoPage lang={onlineData.lang} /> }
|
||||
const ComponentKey = Object.keys(pageComponents)[0];
|
||||
const PageComponent = pageComponents[ComponentKey];
|
||||
if (!PageComponent) { return <ContentToRenderNoPage lang={lang} /> }
|
||||
if (!PageComponent) { return <ContentToRenderNoPage lang={onlineData.lang} /> }
|
||||
return <PageComponent
|
||||
lang={lang}
|
||||
activePageUrl={activePageUrl}
|
||||
mode={mode}
|
||||
userData={userData}
|
||||
userLoading={userLoading}
|
||||
userError={userError}
|
||||
selectionData={selectionData}
|
||||
selectionLoading={selectionLoading}
|
||||
selectionError={selectionError}
|
||||
useReloadWindow={useReloadWindow}
|
||||
activePageUrl={activePageUrl} searchParams={searchParams}
|
||||
userData={userData} userLoading={userLoading} userError={userError} refreshUser={refreshUser} updateUser={updateUser}
|
||||
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline}
|
||||
/>;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,82 +1,68 @@
|
|||
'use client';
|
||||
|
||||
import { FC, Suspense, useMemo, memo } from "react";
|
||||
import { FC, Suspense, memo } from "react";
|
||||
import { ContentProps, ModeTypes, ModeTypesList } from "@/validations/mutual/dashboard/props";
|
||||
import { LanguageTypes } from "@/validations/mutual/language/validations";
|
||||
import PageToBeChildrendMulti from "./PageToBeChildrendMulti";
|
||||
import LoadingContent from "@/components/mutual/loader/component";
|
||||
|
||||
// Create a memoized version of PageToBeChildrendMulti to prevent unnecessary re-renders
|
||||
const MemoizedMultiPage = memo(PageToBeChildrendMulti);
|
||||
|
||||
// const ContentComponent: FC<ContentProps> = async ({ lang, translations, activePageUrl, isMulti, mode }) => {
|
||||
// const modeFromQuery = ModeTypesList.includes(mode || '') ? mode : 'shortList'
|
||||
// const renderProps = { lang, translations, activePageUrl, mode: modeFromQuery as ModeTypes }
|
||||
// const PageToBeChildrend = isMulti ? PageToBeChildrendMulti : PageToBeChildrendSingle
|
||||
// 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)]"
|
||||
// return <div className={classNameDiv}><Suspense fallback={loadingContent}><PageToBeChildrend {...renderProps} /></Suspense></div>
|
||||
// };
|
||||
const translations = {
|
||||
en: {
|
||||
errorLoadingContent: "Error Loading Content",
|
||||
contentArea: "Content Area",
|
||||
contentLoading: "Content Loading",
|
||||
contentLoadingDescription: "The requested page is currently unavailable or still loading.",
|
||||
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: string; activePageUrl: string; mode: string }> = memo(({ lang, activePageUrl, mode }) => (
|
||||
const FallbackContent: FC<{ lang: LanguageTypes; activePageUrl: string }> = memo(({ lang, activePageUrl }) => (
|
||||
<div className="p-6 bg-white rounded-lg shadow-md">
|
||||
<h2 className="text-2xl font-bold mb-4">Content Loading</h2>
|
||||
<p className="text-gray-600 mb-4">The requested page is currently unavailable or still loading.</p>
|
||||
<h2 className="text-2xl font-bold mb-4">{translations[lang].contentLoading}</h2>
|
||||
<p className="text-gray-600 mb-4">{translations[lang].contentLoadingDescription}</p>
|
||||
<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">Language: {lang}</p>
|
||||
<p className="text-sm text-blue-700">Mode: {mode}</p>
|
||||
<p className="text-sm text-blue-700">{translations[lang].pageUrl}: {activePageUrl}</p>
|
||||
<p className="text-sm text-blue-700">{translations[lang].language}: {lang}</p>
|
||||
</div>
|
||||
</div>
|
||||
));
|
||||
|
||||
const ContentComponent: FC<ContentProps> = ({
|
||||
lang, activePageUrl, mode,
|
||||
userData, userLoading, userError,
|
||||
selectionData, selectionLoading, selectionError,
|
||||
searchParams, activePageUrl, mode, userData, userLoading, userError, refreshUser, updateUser,
|
||||
onlineData, onlineLoading, onlineError, refreshOnline, updateOnline,
|
||||
}) => {
|
||||
|
||||
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 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 (selectionError || userError) {
|
||||
return <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>
|
||||
<p className="text-gray-600 mb-4">{selectionError || userError}</p>
|
||||
if (userLoading) { return <div className={classNameDiv}>{loadingContent}</div> }
|
||||
if (userError) {
|
||||
return (
|
||||
<div className={classNameDiv}><div className="p-6 bg-white rounded-lg shadow-md">
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div className={classNameDiv}>
|
||||
<Suspense fallback={loadingContent}>
|
||||
<div className="p-6 bg-white rounded-lg shadow-md">
|
||||
<h2 className="text-2xl font-bold mb-4">Content Area</h2>
|
||||
|
||||
{/* Fallback Content */}
|
||||
{(!userData || !selectionData) && (
|
||||
<FallbackContent
|
||||
lang={lang || ''}
|
||||
activePageUrl={activePageUrl || ''}
|
||||
mode={modeFromQuery}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Wrap component in memo to prevent unnecessary re-renders */}
|
||||
<h2 className="text-2xl font-bold mb-4">{translations[lang].contentArea}</h2>
|
||||
{(!userData) && (<FallbackContent lang={lang} activePageUrl={activePageUrl || ''} />)}
|
||||
<MemoizedMultiPage
|
||||
lang={lang || ''}
|
||||
activePageUrl={activePageUrl || ''}
|
||||
mode={modeFromQuery as ModeTypes}
|
||||
userData={userData}
|
||||
userLoading={userLoading}
|
||||
userError={userError}
|
||||
selectionData={selectionData}
|
||||
selectionLoading={selectionLoading}
|
||||
selectionError={selectionError}
|
||||
/>
|
||||
activePageUrl={activePageUrl || ''} searchParams={searchParams}
|
||||
userData={userData} userLoading={userLoading} userError={userError} refreshUser={refreshUser} updateUser={updateUser}
|
||||
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline} />
|
||||
</div>
|
||||
</Suspense>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import { FC } from "react";
|
||||
import { langGetKey } from "@/lib/langGet";
|
||||
import { FooterProps } from "@/validations/mutual/dashboard/props";
|
||||
import { LanguageTypes } from "@/validations/mutual/language/validations";
|
||||
|
||||
const translations = {
|
||||
en: {
|
||||
|
|
@ -15,9 +16,11 @@ const translations = {
|
|||
}
|
||||
|
||||
const FooterComponent: FC<FooterProps> = ({
|
||||
lang, activePageUrl, useReloadWindow, configData, configLoading, configError
|
||||
activePageUrl, configData, configLoading, configError,
|
||||
onlineData, onlineLoading, onlineError
|
||||
}) => {
|
||||
// Use the config context hook
|
||||
const lang = onlineData?.lang as LanguageTypes || 'en';
|
||||
|
||||
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">
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { FC } from "react";
|
|||
import { HeaderProps } from "@/validations/mutual/dashboard/props";
|
||||
import { langGetKey } from "@/lib/langGet";
|
||||
import LanguageSelectionComponent from "@/components/mutual/languageSelection/component";
|
||||
import { LanguageTypes } from "@/validations/mutual/language/validations";
|
||||
|
||||
const translations = {
|
||||
en: {
|
||||
|
|
@ -16,10 +17,10 @@ const translations = {
|
|||
}
|
||||
|
||||
const HeaderComponent: FC<HeaderProps> = ({
|
||||
lang, activePageUrl, prefix, mode,
|
||||
onlineData, onlineLoading, onlineError, refreshOnline, updateOnline,
|
||||
userData, userLoading, userError,
|
||||
activePageUrl, onlineData, onlineLoading, onlineError, refreshOnline, updateOnline,
|
||||
userData, userLoading, userError, refreshUser, updateUser
|
||||
}) => {
|
||||
const lang = onlineData?.lang as LanguageTypes || 'en';
|
||||
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 flex-row justify-center items-center">
|
||||
|
|
@ -29,12 +30,11 @@ const HeaderComponent: FC<HeaderProps> = ({
|
|||
<div className="flex items-center">
|
||||
{!onlineLoading && onlineData && onlineData.userType && (
|
||||
<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>
|
||||
</div>
|
||||
)}<LanguageSelectionComponent
|
||||
lang={lang} activePage={activePageUrl} prefix={prefix}
|
||||
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline}
|
||||
activePage={activePageUrl} onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
'use client';
|
||||
import { FC, Suspense } from "react";
|
||||
import { MenuProps } from "@/validations/mutual/dashboard/props";
|
||||
import { LanguageTypes } from "@/validations/mutual/language/validations";
|
||||
|
||||
import UserProfileSection from "./userProfileSection";
|
||||
import ClientSelectionSection from "./clientSelectionSection";
|
||||
|
|
@ -11,7 +12,7 @@ import MenuEmptyState from "./menuEmptyState";
|
|||
import LoadingContent from "@/components/mutual/loader/component";
|
||||
|
||||
const MenuComponent: FC<MenuProps> = ({
|
||||
lang, activePageUrl, useReloadWindow, availableApplications,
|
||||
activePageUrl, availableApplications, prefix,
|
||||
onlineData, onlineLoading, onlineError,
|
||||
userData, userLoading, userError,
|
||||
selectionData, selectionLoading, selectionError,
|
||||
|
|
@ -21,21 +22,21 @@ const MenuComponent: FC<MenuProps> = ({
|
|||
if (menuError) { return <MenuErrorState error={menuError} />; } // Render error state
|
||||
if (availableApplications.length === 0) { return <MenuEmptyState />; } // Render empty state
|
||||
function handleClientSelection(client: any) { console.log('Client selected:', client) }
|
||||
const lang = onlineData?.lang as LanguageTypes || 'en';
|
||||
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="flex flex-col">
|
||||
{/* 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} />
|
||||
</Suspense>
|
||||
{/* 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} />
|
||||
</Suspense>
|
||||
|
||||
{/* Menu Items Section */}
|
||||
<Suspense fallback={<div><LoadingContent height="h-16" size="w-36 h-48" key={"loading-conent"} plane="h-full w-full" /></div>}>
|
||||
<MenuItemsSection availableApplications={availableApplications} activePageUrl={activePageUrl} lang={lang} />
|
||||
<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} prefix={prefix} />
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
'use client';
|
||||
|
||||
import { FC, useState, useEffect } from "react";
|
||||
import React, { FC, useEffect, useState } from "react";
|
||||
import { menuTranslation } from "@/languages/mutual/menu";
|
||||
import FirstLayerDropdown from "./firstLayerComponent";
|
||||
import SecondLayerDropdown from "./secondLayerComponent";
|
||||
import ThirdLayerDropdown from "./thirdLayerComponent";
|
||||
import { parseURlFormString } from "@/lib/menuGet";
|
||||
import { menuTranslation } from "@/languages/mutual/menu";
|
||||
|
||||
// Define types for menu structure
|
||||
type ThirdLayerItem = Record<string, any>;
|
||||
type TranslationItem = { value: string; key: string };
|
||||
type ThirdLayerItemData = { path: string; translation: TranslationItem[] };
|
||||
type ThirdLayerItem = Record<string, ThirdLayerItemData>;
|
||||
type SecondLayerItems = Record<string, ThirdLayerItem>;
|
||||
type FirstLayerItems = Record<string, SecondLayerItems>;
|
||||
type MenuStructure = FirstLayerItems;
|
||||
|
|
@ -17,159 +16,86 @@ interface MenuItemsSectionProps {
|
|||
availableApplications: string[];
|
||||
activePageUrl: string;
|
||||
lang: string;
|
||||
prefix?: string;
|
||||
}
|
||||
|
||||
// Helper function to get translation for a URL path
|
||||
const getMenuTranslation = (translations: any, urlPath: string) => {
|
||||
if (translations[urlPath]) {
|
||||
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;
|
||||
const menuStaticTranslation = {
|
||||
tr: { menu: "Menü" },
|
||||
en: { menu: "Menu" }
|
||||
}
|
||||
|
||||
if (cleanUrlPath.includes(cleanKey) || cleanKey.includes(cleanUrlPath)) {
|
||||
return translations[key];
|
||||
}
|
||||
}
|
||||
const parts = urlPath.split('/');
|
||||
return parts[parts.length - 1] || urlPath;
|
||||
};
|
||||
|
||||
const MenuItemsSection: FC<MenuItemsSectionProps> = ({ availableApplications, activePageUrl, lang }) => {
|
||||
const MenuItemsSection: FC<MenuItemsSectionProps> = ({ availableApplications, activePageUrl, lang, prefix }) => {
|
||||
const [expandedFirstLayer, setExpandedFirstLayer] = useState<string | null>(null);
|
||||
const [expandedSecondLayer, setExpandedSecondLayer] = useState<string | null>(null);
|
||||
const [menuStructure, setMenuStructure] = useState<MenuStructure>({});
|
||||
|
||||
const menuTranslationWLang = menuTranslation[lang as keyof typeof menuTranslation];
|
||||
const activePathLayers = parseURlFormString(activePageUrl).data;
|
||||
const activeFirstLayer = activePathLayers[0] || null;
|
||||
const activeSecondLayer = activePathLayers[1] || null;
|
||||
const activeThirdLayer = activePathLayers.slice(2, activePathLayers.length).join("/");
|
||||
const activeParsedLayer = (menuTranslationWLang[activePageUrl as keyof typeof menuTranslationWLang] as unknown as TranslationItem[]) || [];
|
||||
const activeFirstLayer = activeParsedLayer[0] ? activeParsedLayer[0].key : null;
|
||||
const activeSecondLayer = activeParsedLayer[1] ? activeParsedLayer[1].key : null;
|
||||
const activeThirdLayer = activeParsedLayer[2] ? activeParsedLayer[2].key : null;
|
||||
|
||||
useEffect(() => {
|
||||
const newMenuStructure: MenuStructure = {};
|
||||
availableApplications.forEach((appPath: string) => {
|
||||
const cleanPath = appPath.startsWith('/') ? appPath.substring(1) : appPath;
|
||||
const pathParts = cleanPath.split('/');
|
||||
if (pathParts.length >= 3) {
|
||||
const firstLayer = pathParts[0];
|
||||
const secondLayer = pathParts[1];
|
||||
const thirdLayer = pathParts.slice(2).join('/');
|
||||
const pathTranslation = menuTranslationWLang[appPath as keyof typeof menuTranslationWLang] as unknown as TranslationItem[] | undefined;
|
||||
if (pathTranslation && pathTranslation.length >= 3) {
|
||||
const firstLayer = pathTranslation[0] ? pathTranslation[0].key : '';
|
||||
const secondLayer = pathTranslation[1] ? pathTranslation[1].key : '';
|
||||
const thirdLayer = pathTranslation[2] ? pathTranslation[2].key : '';
|
||||
if (!newMenuStructure[firstLayer]) { newMenuStructure[firstLayer] = {} }
|
||||
if (!newMenuStructure[firstLayer][secondLayer]) { newMenuStructure[firstLayer][secondLayer] = {} }
|
||||
newMenuStructure[firstLayer][secondLayer][thirdLayer] = true;
|
||||
newMenuStructure[firstLayer][secondLayer][thirdLayer] = { path: appPath, translation: pathTranslation };
|
||||
}
|
||||
});
|
||||
setMenuStructure(newMenuStructure);
|
||||
}, [availableApplications]);
|
||||
}, [availableApplications, menuTranslationWLang]);
|
||||
|
||||
useEffect(() => {
|
||||
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)
|
||||
}
|
||||
};
|
||||
useEffect(() => { 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 renderThirdLayerItems = (firstLayerKey: string, secondLayerKey: string, thirdLayerItems: ThirdLayerItem) => {
|
||||
const baseUrl = `/${firstLayerKey}/${secondLayerKey}`;
|
||||
return Object.keys(thirdLayerItems).map(thirdLayerKey => {
|
||||
return Object.entries(thirdLayerItems).map(([thirdLayerKey, itemData]) => {
|
||||
const isActive = activeFirstLayer === firstLayerKey && activeSecondLayer === secondLayerKey && activeThirdLayer === thirdLayerKey;
|
||||
const mergeUrl = `${baseUrl}/${thirdLayerKey}`;
|
||||
const url = `/${lang}${baseUrl}/${thirdLayerKey}`;
|
||||
return (
|
||||
<div key={`${thirdLayerKey}-item`} className="ml-2 my-1">
|
||||
<ThirdLayerDropdown
|
||||
isActive={isActive}
|
||||
innerText={getMenuTranslation(menuTranslationWLang, mergeUrl)}
|
||||
url={url}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
const url = itemData ? itemData.path || '' : '';
|
||||
const translation = itemData ? itemData.translation || [] : [];
|
||||
const displayText = translation[2]?.value || thirdLayerKey;
|
||||
return <div key={`${thirdLayerKey}-item`} className="ml-2 my-1"><ThirdLayerDropdown isActive={isActive} innerText={displayText} url={`${prefix}${url}`} /></div>;
|
||||
});
|
||||
};
|
||||
|
||||
const renderSecondLayerItems = (firstLayerKey: string, secondLayerItems: SecondLayerItems) => {
|
||||
return Object.entries(secondLayerItems).map(([secondLayerKey, thirdLayerItems]) => {
|
||||
const isActive = activeFirstLayer === firstLayerKey && activeSecondLayer === 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 (
|
||||
<div key={`${secondLayerKey}-item`} className="ml-2 my-1">
|
||||
<SecondLayerDropdown
|
||||
isActive={isActive}
|
||||
isExpanded={isExpanded}
|
||||
innerText={getMenuTranslation(menuTranslationWLang, mergeUrl)}
|
||||
onClick={() => handleSecondLayerClick(secondLayerKey)}
|
||||
/>
|
||||
{isExpanded && (
|
||||
<div className="ml-2 mt-1">
|
||||
{renderThirdLayerItems(firstLayerKey, secondLayerKey, thirdLayerItems)}
|
||||
</div>
|
||||
)}
|
||||
<SecondLayerDropdown isActive={isActive} isExpanded={isExpanded} innerText={displayText} onClick={() => handleSecondLayerClick(secondLayerKey)} />
|
||||
{isExpanded && <div className="ml-2 mt-1">{renderThirdLayerItems(firstLayerKey, secondLayerKey, thirdLayerItems)}</div>}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const renderFirstLayerItems = () => {
|
||||
return Object.entries(menuStructure).map(([firstLayerKey, secondLayerItems]) => {
|
||||
const isActive = activeFirstLayer === 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 (
|
||||
<div key={`${firstLayerKey}-item`} className="mb-2">
|
||||
<FirstLayerDropdown
|
||||
isActive={isActive}
|
||||
isExpanded={isExpanded}
|
||||
innerText={getMenuTranslation(menuTranslationWLang, mergeUrl)}
|
||||
onClick={() => handleFirstLayerClick(firstLayerKey)}
|
||||
/>
|
||||
{isExpanded && (
|
||||
<div className="mt-1">
|
||||
{renderSecondLayerItems(firstLayerKey, secondLayerItems)}
|
||||
</div>
|
||||
)}
|
||||
<FirstLayerDropdown isActive={isActive} isExpanded={isExpanded} innerText={displayText} onClick={() => handleFirstLayerClick(firstLayerKey)} />
|
||||
{isExpanded && <div className="mt-1">{renderSecondLayerItems(firstLayerKey, secondLayerItems)}</div>}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="mt-1">
|
||||
<h3 className="text-sm font-semibold mb-1">Menu</h3>
|
||||
{renderFirstLayerItems()}
|
||||
</div>
|
||||
);
|
||||
return <div className="mt-1"><h3 className="text-sm font-semibold mb-1">{menuStaticTranslation[lang as keyof typeof menuStaticTranslation].menu}</h3>{renderFirstLayerItems()}</div>;
|
||||
};
|
||||
|
||||
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="flex items-center">
|
||||
<div className="mr-2">
|
||||
{userData && userData.avatar ? (
|
||||
<img className="rounded-full border border-white" src={userData.avatar} alt="Avatar" width={40} height={40} />
|
||||
) : (
|
||||
{userData && userData.avatar ? (<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="text-white text-sm font-bold">{userData?.email ? userData.email.slice(0, 2).toUpperCase() : 'U'}</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ async function setContextPageOnline(
|
|||
body: JSON.stringify(setOnline),
|
||||
signal: controller.signal,
|
||||
});
|
||||
console.log("result", await result.json());
|
||||
|
||||
// Clear the timeout
|
||||
clearTimeout(timeoutId);
|
||||
|
|
|
|||
|
|
@ -7,9 +7,7 @@ import { LanguageTypes } from "@/validations/mutual/language/validations";
|
|||
import LanguageSelectionItem from "./languageItem";
|
||||
|
||||
interface LanguageSelectionComponentProps {
|
||||
lang: LanguageTypes;
|
||||
activePage: string;
|
||||
prefix: string;
|
||||
onlineData: any;
|
||||
onlineLoading: boolean;
|
||||
onlineError: any;
|
||||
|
|
@ -17,13 +15,14 @@ interface LanguageSelectionComponentProps {
|
|||
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 getPageWithLocale = (locale: LanguageTypes): string => { return `${prefix}/${activePage}` }
|
||||
const languageButtons = [
|
||||
{ activeLang: lang, buttonsLang: "en", refUrl: getPageWithLocale("en"), innerText: langGetKey(translations, "english") },
|
||||
{ activeLang: lang, buttonsLang: "tr", refUrl: getPageWithLocale("tr"), innerText: langGetKey(translations, "turkish") }
|
||||
]
|
||||
{ activeLang: lang, buttonsLang: "en", refUrl: "en", innerText: langGetKey(translations, "english") },
|
||||
{ activeLang: lang, buttonsLang: "tr", refUrl: "tr", innerText: langGetKey(translations, "turkish") }
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="flex items-end justify-end">
|
||||
<DropdownMenu>
|
||||
|
|
@ -32,8 +31,8 @@ const LanguageSelectionComponent: React.FC<LanguageSelectionComponentProps> = ({
|
|||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
{languageButtons.map((props, index) => (
|
||||
<LanguageSelectionItem key={props.buttonsLang} {...props} onlineData={onlineData}
|
||||
onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline} />
|
||||
<LanguageSelectionItem key={props.buttonsLang} {...props}
|
||||
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline} />
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</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 = {
|
||||
"/definitions": "Definitions",
|
||||
"/definitions/identifications": "Identifications",
|
||||
"/definitions/identifications/people": "People",
|
||||
"/definitions/identifications/users": "Users",
|
||||
// New menu
|
||||
"/dashboard": [
|
||||
{ value: "Dashboard", key: "dashboard" },
|
||||
{ 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",
|
||||
"/definitions/building/parts": "Build Parts",
|
||||
"/definitions/building/areas": "Building Areas",
|
||||
|
||||
"/building": "Building",
|
||||
"/building/accounts": "Account Actions",
|
||||
"/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": "Meetings",
|
||||
"/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",
|
||||
// Early menu
|
||||
"/definitions/identifications/people": [
|
||||
{ value: "Definitions", key: "definitions" },
|
||||
{ value: "Identifications", key: "identifications" },
|
||||
{ value: "People", key: "people" },
|
||||
],
|
||||
"/definitions/identifications/users": [
|
||||
{ value: "Definitions", key: "definitions" },
|
||||
{ value: "Identifications", key: "identifications" },
|
||||
{ value: "Users", key: "users" },
|
||||
],
|
||||
"/definitions/building/parts": [
|
||||
{ value: "Definitions", key: "definitions" },
|
||||
{ value: "Building", key: "building" },
|
||||
{ value: "Parts", key: "parts" },
|
||||
],
|
||||
"/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, 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 = {
|
||||
"/definitions": "Tanımlamalar",
|
||||
"/definitions/identifications": "Tanımlamalar",
|
||||
"/definitions/identifications/people": "Kişiler",
|
||||
"/definitions/identifications/users": "Kullanıcılar",
|
||||
// New menu
|
||||
"/dashboard": [
|
||||
{ value: "Dashboard", key: "dashboard" },
|
||||
{ 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",
|
||||
"/definitions/building/parts": "Daireler",
|
||||
"/definitions/building/areas": "Bina Alanları",
|
||||
|
||||
"/building": "Bina",
|
||||
"/building/accounts": "Account Eylemleri",
|
||||
"/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": "Toplantılar",
|
||||
"/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",
|
||||
// Early menu
|
||||
"/definitions/identifications/people": [
|
||||
{ value: "Tanımlamalar", key: "definitions" },
|
||||
{ value: "Tanımlamalar", key: "identifications" },
|
||||
{ value: "Kişiler", key: "people" },
|
||||
],
|
||||
"/definitions/identifications/users": [
|
||||
{ value: "Tanımlamalar", key: "definitions" },
|
||||
{ value: "Tanımlamalar", key: "identifications" },
|
||||
{ value: "Kullanıcılar", key: "users" },
|
||||
],
|
||||
"/definitions/building/parts": [
|
||||
{ value: "Tanımlamalar", key: "definitions" },
|
||||
{ value: "Bina", key: "building" },
|
||||
{ value: "Daireler", key: "parts" },
|
||||
],
|
||||
"/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 };
|
||||
|
|
|
|||
|
|
@ -1,68 +1,48 @@
|
|||
'use client';
|
||||
|
||||
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 React, { FC } from 'react';
|
||||
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 type { LanguageTypes } from "@/validations/mutual/language/validations";
|
||||
|
||||
// Import all context hooks
|
||||
import { useMenu } from "@/components/mutual/context/menu/context";
|
||||
import { useOnline } from "@/components/mutual/context/online/context";
|
||||
import { useSelection } from "@/components/mutual/context/selection/context";
|
||||
import { useUser } from "@/components/mutual/context/user/context";
|
||||
import { useConfig } from "@/components/mutual/context/config/context";
|
||||
|
||||
interface ClientLayoutProps {
|
||||
allProps: {
|
||||
lang: LanguageTypes;
|
||||
activePageUrl: string;
|
||||
mode: ModeTypes;
|
||||
prefix: string;
|
||||
};
|
||||
packs?: {
|
||||
menu?: ClientMenu;
|
||||
selection?: ClientSelection;
|
||||
user?: ClientUser;
|
||||
settings?: ClientSettings;
|
||||
online?: ClientOnline;
|
||||
};
|
||||
useReloadWindow?: () => void;
|
||||
}
|
||||
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";
|
||||
|
||||
interface ClientLayoutProps { activePageUrl: string, searchParams: Record<string, any> }
|
||||
|
||||
const ClientLayout: FC<ClientLayoutProps> = ({ activePageUrl, searchParams }) => {
|
||||
|
||||
const ClientLayout: FC<ClientLayoutProps> = ({ allProps }) => {
|
||||
const { onlineData, isLoading: onlineLoading, error: onlineError, refreshOnline, updateOnline } = useOnline();
|
||||
const { userData, isLoading: userLoading, error: userError } = useUser();
|
||||
const { availableApplications, isLoading: menuLoading, error: menuError, menuData, refreshMenu } = useMenu();
|
||||
const { selectionData, isLoading: selectionLoading, error: selectionError } = useSelection();
|
||||
const { configData, isLoading: configLoading, error: configError } = useConfig();
|
||||
const { userData, isLoading: userLoading, error: userError, refreshUser, updateUser } = useUser();
|
||||
const { availableApplications, isLoading: menuLoading, error: menuError, menuData, refreshMenu, updateMenu } = useMenu();
|
||||
const { selectionData, isLoading: selectionLoading, error: selectionError, refreshSelection, updateSelection } = useSelection();
|
||||
const { configData, isLoading: configLoading, error: configError, refreshConfig, updateConfig } = useConfig();
|
||||
const prefix = "/panel"
|
||||
const mode = (searchParams?.mode as ModeTypes) || 'shortList';
|
||||
console.log("onlineData", onlineData)
|
||||
|
||||
return (
|
||||
<ClientProviders>
|
||||
<div className="flex flex-col min-w-screen">
|
||||
<HeaderComponent {...allProps}
|
||||
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError}
|
||||
refreshOnline={refreshOnline} updateOnline={updateOnline}
|
||||
userData={userData} userLoading={userLoading} userError={userError}
|
||||
/>
|
||||
<MenuComponent {...allProps}
|
||||
availableApplications={availableApplications}
|
||||
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError}
|
||||
userData={userData} userLoading={userLoading} userError={userError}
|
||||
selectionData={selectionData} selectionLoading={selectionLoading} selectionError={selectionError}
|
||||
menuData={menuData} menuLoading={menuLoading} menuError={menuError} />
|
||||
<ContentComponent {...allProps}
|
||||
userData={userData} userLoading={userLoading} userError={userError}
|
||||
selectionData={selectionData} selectionLoading={selectionLoading} selectionError={selectionError}
|
||||
/>
|
||||
<FooterComponent {...allProps}
|
||||
availableApplications={availableApplications}
|
||||
configData={configData} configLoading={configLoading} configError={configError}
|
||||
/>
|
||||
<HeaderComponent activePageUrl={activePageUrl} searchParams={searchParams}
|
||||
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline}
|
||||
userData={userData} userLoading={userLoading} userError={userError} refreshUser={refreshUser} updateUser={updateUser} />
|
||||
<MenuComponent availableApplications={availableApplications} activePageUrl={activePageUrl} prefix={prefix} searchParams={searchParams}
|
||||
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline}
|
||||
userData={userData} userLoading={userLoading} userError={userError} refreshUser={refreshUser} updateUser={updateUser}
|
||||
selectionData={selectionData} selectionLoading={selectionLoading} selectionError={selectionError} refreshSelection={refreshSelection} updateSelection={updateSelection}
|
||||
menuData={menuData} menuLoading={menuLoading} menuError={menuError} refreshMenu={refreshMenu} updateMenu={updateMenu} />
|
||||
<ContentComponent activePageUrl={activePageUrl} mode={mode} searchParams={searchParams}
|
||||
userData={userData} userLoading={userLoading} userError={userError} refreshUser={refreshUser} updateUser={updateUser}
|
||||
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline} />
|
||||
<FooterComponent activePageUrl={activePageUrl} searchParams={searchParams}
|
||||
configData={configData} configLoading={configLoading} configError={configError} refreshConfig={refreshConfig} updateConfig={updateConfig}
|
||||
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline} />
|
||||
</div>
|
||||
</ClientProviders>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
'use server';
|
||||
import { FC } from "react";
|
||||
import { DashboardLayoutProps, ModeTypes } from "@/validations/mutual/dashboard/props";
|
||||
import { DashboardLayoutProps } from "@/validations/mutual/dashboard/props";
|
||||
import { ClientLayout } from "./client";
|
||||
|
||||
const DashboardLayout: FC<DashboardLayoutProps> = async ({ params, searchParams, lang }) => {
|
||||
const mode = (searchParams?.mode as ModeTypes) || 'shortList';
|
||||
const activePageUrl = `/${params.page?.join('/')}`;
|
||||
const allProps = { lang: lang || '', activePageUrl, mode, prefix: "/panel" };
|
||||
return <ClientLayout allProps={allProps} />
|
||||
const DashboardLayout: FC<DashboardLayoutProps> = async ({ params, searchParams }) => {
|
||||
const activePageUrl = `/${params.page?.join('/')}`; return <ClientLayout activePageUrl={activePageUrl} searchParams={searchParams} />
|
||||
}
|
||||
|
||||
export { DashboardLayout };
|
||||
|
|
|
|||
|
|
@ -1,8 +1,85 @@
|
|||
import { ContentProps } from "@/validations/mutual/dashboard/props";
|
||||
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>>> = {
|
||||
"/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": {
|
||||
superUserBuildingPartsTenantSomething,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import pageIndexMulti from "@/pages/multi/index";
|
|||
import pageIndexSingle from "@/pages/single/index";
|
||||
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 {
|
||||
return `${activePageUrl}` in pageIndexSingle ? pageIndexSingle[`${activePageUrl}`] : ContentToRenderNoPage
|
||||
} catch (error) {
|
||||
|
|
@ -16,7 +16,7 @@ async function resolveWhichPageToRenderSingle({ activePageUrl }: ResolverProps):
|
|||
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
|
||||
try {
|
||||
const ApplicationToRender = pageIndexMulti[activePageUrl][pageToRender]
|
||||
|
|
|
|||
|
|
@ -16,49 +16,9 @@ type ModeTypes = "shortList" | "fullList" | "create" | "update" | "view";
|
|||
const ModeTypesList = ["shortList", "fullList", "create", "update", "view"];
|
||||
|
||||
interface ContentProps {
|
||||
lang: LanguageTypes;
|
||||
activePageUrl: string;
|
||||
mode?: ModeTypes;
|
||||
userData: 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;
|
||||
searchParams: Record<string, any>;
|
||||
onlineData: any;
|
||||
onlineLoading: boolean;
|
||||
onlineError: any;
|
||||
|
|
@ -67,6 +27,65 @@ interface HeaderProps {
|
|||
userData: any;
|
||||
userLoading: boolean;
|
||||
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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue