side Menu updated

This commit is contained in:
berkay 2025-01-07 22:25:30 +03:00
parent c1f517d32d
commit 2dd267a570
42 changed files with 1040 additions and 102 deletions

View File

@ -87,7 +87,6 @@ async function retrieveUserSelection() {
const buildNo = availableOccupants?.build_no;
let selectedOccupant: any = null;
const occupants = availableOccupants?.occupants;
console.log("occupants", occupants);
if (occupants) {
selectedOccupant = occupants.find(
(occupant: any) =>

View File

@ -3,9 +3,31 @@ import { fetchDataWithToken } from "../api-fetcher";
import { cookies } from "next/headers";
import { baseUrl, cookieObject, tokenSecret } from "../basics";
import NextCrypto from "next-crypto";
import { PagesInfosAndEndpoints } from "@/apimaps/mappingApi";
const availableEventsURL = `${baseUrl}/access/endpoints/available`;
async function checkPageAvaliablityByEndpoint(availableEvents: any) {
let availablePages: string[] = [];
const availableEventsList: string[] = availableEvents || [];
PagesInfosAndEndpoints.map((page) => {
const pageInfo = page?.pageInfo?.tr || [];
if (pageInfo.length > 0) {
pageInfo.map((pageInfoItem) => {
const endpoint = pageInfoItem?.endpoint || "";
if (
availableEventsList.includes(endpoint) &&
!availablePages.includes(page.name)
) {
availablePages.push(page.name);
return;
}
});
}
});
return availablePages;
}
async function setAvailableEvents() {
const cookieStore = await cookies();
const nextCrypto = new NextCrypto(tokenSecret);
@ -19,6 +41,10 @@ async function setAvailableEvents() {
if (availableResponse.status === 200) {
const availableEventData = Array.from(availableResponse?.result) || [];
const availableEventDataRes = await checkPageAvaliablityByEndpoint(
availableEventData
);
console.log("availableEventDataRes", availableEventDataRes);
const availableEvents = await nextCrypto.encrypt(
JSON.stringify({ availableEvents: availableEventData })
);

View File

@ -1,9 +1,10 @@
"use server";
import NextCrypto from "next-crypto";
import { fetchData, fetchDataWithToken } from "../api-fetcher";
import { cookies } from "next/headers";
import { baseUrl, cookieObject, tokenSecret } from "../basics";
import NextCrypto from "next-crypto";
// import { setAvailableEvents } from "../events/available";
import { setAvailableEvents } from "../events/available";
const loginEndpoint = `${baseUrl}/authentication/login`;
const loginSelectEndpoint = `${baseUrl}/authentication/select`;
@ -92,6 +93,7 @@ async function loginSelectEmployee(payload: LoginSelectEmployee) {
false
);
if (selectResponse.status === 200) {
await setAvailableEvents();
const usersSelection = await nextCrypto.encrypt(
JSON.stringify({
company_uu_id: payload.company_uu_id,
@ -137,7 +139,7 @@ async function loginSelectOccupant(payload: LoginSelectOccupant) {
value: usersSelection,
...cookieObject,
});
// await setAvailableEvents();
await setAvailableEvents();
}
return selectResponse;
}

View File

@ -43,6 +43,7 @@ async function retrieveHeadersAndValidationByEndpoint({
"POST",
false
);
if (selectResponse.status === 200) {
const responseParsed = new HeadersAndValidations(selectResponse);
return {

View File

@ -6,7 +6,7 @@ const AccountSubCategories = [
},
icon: "LucideLandmark",
component: null,
selfEndpoints: ["/account/records/list"],
url: "/accounts/balance-inquiry",
allEndpoints: [],
subCategories: [],
},

View File

@ -3,38 +3,38 @@ import { PartsPageInfo } from "../parts/pageInfo";
const BuildCategories = [
{
name: "BuildingPartPage",
title: {
tr: "Daireler",
en: "Flats",
},
icon: "DoorOpen",
component: "PartsPage",
url: "/building/parts",
pageInfo: PartsPageInfo,
allEndpoints: [],
subCategories: [],
},
{
name: "BuildingAreaPage",
title: {
tr: "Kullanılabilir Alanlar",
en: "Building Areas",
},
icon: "TreePine",
component: null,
selfEndpoints: [
"/building/area/list",
"/building/area/create",
"/building/area/update/{build_uu_id}",
],
url: "/building/areas",
pageInfo: null,
allEndpoints: [],
subCategories: [],
},
{
name: "LivingSpacePage",
title: {
tr: "Yaşayan Kişiler",
en: "Living People",
},
icon: "UsersRound",
url: "/building/living-space",
component: "LivingSpacePage",
pageInfo: LivingSpaceInfo,
allEndpoints: [],

View File

@ -5,12 +5,7 @@ const CompanyCategories = [
en: "Departments",
},
icon: "FolderOpenDot",
component: null,
selfEndpoints: [
"/department/list",
"/department/create",
"/department/update/{department_uu_id}",
],
url: "/companies/departments",
allEndpoints: [],
subCategories: [],
},
@ -20,8 +15,7 @@ const CompanyCategories = [
en: "Duties",
},
icon: "BriefcaseMedical",
component: null,
selfEndpoints: ["/duties/list", "/duties/create", "/duties/update"],
url: "/companies/duties",
allEndpoints: [],
subCategories: [],
},
@ -31,14 +25,7 @@ const CompanyCategories = [
en: "Employees",
},
icon: "Pickaxe",
component: null,
selfEndpoints: [
"/employee/list",
"/employee/create",
"/employee/update/{employee_uu_id}",
"/employee/employ",
"/employee/fire",
],
url: "/companies/employees",
allEndpoints: [],
subCategories: [],
},
@ -48,12 +35,7 @@ const CompanyCategories = [
en: "Staff",
},
icon: "BicepsFlexed",
component: null,
selfEndpoints: [
"/staff/list",
"/staff/create",
"/staff/update/{staff_uu_id}",
],
url: "/companies/staff",
allEndpoints: [],
subCategories: [],
},

View File

@ -72,32 +72,24 @@ const ProjectBookItemsCategories = [
const DecisionBookSubCategories = [
{
name: "DecisionsPage",
title: {
tr: "Kararlar",
en: "Decisions",
},
icon: "ScrollText",
component: "",
selfEndpoints: [
"/build/decision_book/items/list",
"/build/decision_book/items/create",
"/build/decision_book/items/update/{decision_book_item_uu_id}",
],
url: "/decisions/decision-book",
allEndpoints: DecisionBookItemAllEndpoints,
subCategories: DecisionBookCategories,
},
{
name: "ProjectsPage",
title: {
tr: "Proje Dosyaları",
en: "Project Files",
},
icon: "Projector",
component: "",
selfEndpoints: [
"/build/decision_book/project/list",
"/build/decision_book/project/create",
"/build/decision_book/project/update/{project_uu_id}",
],
url: "/decisions/projects",
allEndpoints: ProjectBookItemsAllEndpoints,
subCategories: ProjectBookItemsCategories,
},

View File

@ -12,7 +12,7 @@ import {
import { IdentityAllEndpoints } from "./identity/pageInfo";
import { AccesibleAllEndpoints } from "./accesible/pageInfo";
import { CompanyAllEndpoints, CompanyPageInfo } from "./company/pageInfo";
import { MeetingAllEndpoints } from "./meeting/pageInfo";
import { MeetingAllEndpoints, MeetingPageInfo } from "./meeting/pageInfo";
import { AccountAllEndpoints, AccountPageInfo } from "./accounts/pageInfo";
import { BuildPageInfo, BuildAllEndpoints } from "./building/pageInfo";
@ -37,71 +37,65 @@ const PagesInfosAndEndpoints = [
},
icon: "Logs",
url: "/meetings",
pageInfo: null,
component: null,
pageInfo: MeetingPageInfo,
allEndpoints: MeetingAllEndpoints,
subCategories: MeetingSubCategories,
},
{
name: "",
name: "AccountPage",
title: {
tr: "Cari Hesaplar",
en: "Accounts",
},
icon: "Landmark",
component: "AccountPage",
url: "/accounts",
pageInfo: AccountPageInfo,
allEndpoints: AccountAllEndpoints,
subCategories: AccountSubCategories,
},
{
name: "",
name: "DecisionBookPage",
title: {
tr: "Karar Defteri",
en: "Decision Book",
},
icon: "ScrollText",
component: "DecisionBookPage",
url: "/decisions",
pageInfo: DecisionBookPageInfo,
allEndpoints: DecisionBookAllEndpoints,
subCategories: DecisionBookSubCategories,
},
{
name: "",
name: "IdentitiesPage",
title: {
tr: "Kimlikler",
en: "Identities",
},
icon: "UserPlus",
component: null,
url: "/identities",
pageInfo: null,
allEndpoints: IdentityAllEndpoints,
subCategories: IdentityCategories,
},
{
name: "",
name: "AccesibilityPage",
title: {
tr: "Erişilebilirlik",
en: "Accessibility",
},
icon: "Cog",
component: null,
url: "/accessibilities",
pageInfo: null,
allEndpoints: AccesibleAllEndpoints,
subCategories: AccesibleCategories,
},
{
name: "",
name: "CompanyPage",
title: {
tr: "Firmalar",
en: "Companies",
},
icon: "Store",
component: "CompanyPage",
url: "/companies",
pageInfo: CompanyPageInfo,
allEndpoints: CompanyAllEndpoints,
@ -110,10 +104,11 @@ const PagesInfosAndEndpoints = [
];
const AvailableLanguages = ["tr", "en"];
type LanguagesSelectable = "tr" | "en";
interface LanguagesInterface {
tr: string;
en: string;
}
export type { LanguagesInterface };
export type { LanguagesInterface, LanguagesSelectable };
export { PagesInfosAndEndpoints, AvailableLanguages };

View File

@ -5,4 +5,53 @@ const MeetingAllEndpoints = [
"/build/decision_book/invitations/assign",
];
export { MeetingAllEndpoints };
const MeetingPageInfo = {
tr: [
{
title: "Toplantı Listesi",
icon: null,
description: "Toplantı listeyebilirsiniz",
endpoint: "",
component: "Table",
},
{
title: "Toplantı Ekle",
icon: "BadgePlus",
description: "Toplantı oluşturma sayfasına hoş geldiniz",
endpoint: "/building/living_space/create",
component: "AddCreate2Table",
},
{
title: "Toplantı Güncelle",
icon: "Pencil",
description: "Toplantı güncelleme sayfasına hoş geldiniz",
endpoint: "/building/living_space/update/{build_uu_id}",
component: "AddUpdate2Table",
},
],
en: [
{
title: "Meeting List",
icon: null,
description: "Welcome to the meeting list page",
endpoint: "",
component: "Table",
},
{
title: "Create Meeting",
icon: "BadgePlus",
description: "Welcome to the meeting creation page",
endpoint: "/building/living_space/create",
component: "AddCreate2Table",
},
{
title: "Update Meeting",
icon: "Pencil",
description: "Welcome to the meeting update page",
endpoint: "/building/living_space/update/{build_uu_id}",
component: "AddUpdate2Table",
},
],
};
export { MeetingAllEndpoints, MeetingPageInfo };

View File

@ -5,7 +5,7 @@ const MeetingSubCategories = [
en: "Invitations",
},
icon: "ClipboardCheck",
component: null,
url: "/meeting/invitations",
selfEndpoints: [
"/build/decision_book/invite/list",
"/build/decision_book/invite/create",
@ -21,7 +21,7 @@ const MeetingSubCategories = [
en: "Assign Task",
},
icon: "ClipboardList",
component: null,
url: "/meeting/assign",
selfEndpoints: [],
allEndpoints: [],
subCategories: [],

View File

@ -1,8 +1,8 @@
"use client";
import {
Hotel,
Logs,
Landmark,
LucideLandmark,
ScrollText,
UserPlus,
Cog,
@ -12,7 +12,6 @@ import {
} from "lucide-react";
import { DoorOpen, TreePine, UsersRound } from "lucide-react";
import { ClipboardList, ClipboardCheck } from "lucide-react";
import { LucideLandmark } from "lucide-react";
import {
Projector,
FolderKey,

View File

@ -1,11 +1,15 @@
"use server";
import React from "react";
import MainBodyWithHeader from "@/components/defaultLayout/MainBodyWithHeader";
import OnConstructionPage from "@/pages/OnConstruction/OnConstruction";
const Accessibilities = async () => {
return (
<div className="overflow-hidden">
<MainBodyWithHeader children={<></>} section="BuildingPage" />
<MainBodyWithHeader
children={OnConstructionPage}
section="BuildingPage"
/>
</div>
);
};

View File

@ -6,7 +6,7 @@ import AccountPage from "@/pages/Account/AccountPage";
const Accounts = async () => {
return (
<div className="overflow-hidden">
<MainBodyWithHeader children={AccountPage} section="BuildingPage" />
<MainBodyWithHeader children={AccountPage} section="AccountPage" />
</div>
);
};

View File

@ -0,0 +1,25 @@
"use server";
import React from "react";
import MainBodyWithHeader from "@/components/defaultLayout/MainBodyWithHeader";
import BuildingAreaPage from "@/pages/Build/BuildingAreaPage";
const BuildingPart = async () => {
const BuildingAreaConcept = {
layer: 2,
currentPage: "BuildingAreaPage",
firstLayer: "BuildingPage",
secondLayer: "BuildingAreaPage",
thirdLayer: null,
};
return (
<div className="overflow-hidden">
<MainBodyWithHeader
children={BuildingAreaPage}
section={BuildingAreaConcept}
/>
</div>
);
};
export default BuildingPart;

View File

@ -0,0 +1,25 @@
"use server";
import React from "react";
import MainBodyWithHeader from "@/components/defaultLayout/MainBodyWithHeader";
import BuildingPage from "@/pages/Build/BuildingPage";
const LivingSpace = async () => {
const LivingSpaceConcept = {
layer: 2,
currentPage: "LivingSpacePage",
firstLayer: "BuildingPage",
secondLayer: "LivingSpacePage",
thirdLayer: null,
};
return (
<div className="overflow-hidden">
<MainBodyWithHeader
children={BuildingPage}
section={LivingSpaceConcept}
/>
</div>
);
};
export default LivingSpace;

View File

@ -5,9 +5,16 @@ import MainBodyWithHeader from "@/components/defaultLayout/MainBodyWithHeader";
import BuildingPage from "@/pages/Build/BuildingPage";
const BuildinPage = async () => {
const BuildingConcept = {
layer: 1,
currentPage: "BuildingPage",
firstLayer: "BuildingPage",
secondLayer: null,
thirdLayer: null,
};
return (
<div className="overflow-hidden">
<MainBodyWithHeader children={BuildingPage} section="BuildingPage" />
<MainBodyWithHeader children={BuildingPage} section={BuildingConcept} />
</div>
);
};

View File

@ -0,0 +1,23 @@
"use server";
import MainBodyWithHeader from "@/components/defaultLayout/MainBodyWithHeader";
import BuildingPartPage from "@/pages/Build/BuildingPartPage";
const BuildingPart = async () => {
const BuildingPartsConcept = {
layer: 2,
currentPage: "BuildingPartPage",
firstLayer: "BuildingPage",
secondLayer: "BuildingPartPage",
thirdLayer: null,
};
return (
<div className="overflow-hidden">
<MainBodyWithHeader
children={BuildingPartPage}
section={BuildingPartsConcept}
/>
</div>
);
};
export default BuildingPart;

View File

@ -1,11 +1,12 @@
"use server";
import React from "react";
import MainBodyWithHeader from "@/components/defaultLayout/MainBodyWithHeader";
import CompaniesPage from "@/pages/Companies/CompaniesPage";
const Companies = async () => {
return (
<div className="overflow-hidden">
<MainBodyWithHeader children={<></>} section="CompaniesPage" />
<MainBodyWithHeader children={CompaniesPage} section="CompanyPage" />
</div>
);
};

View File

@ -1,5 +1,6 @@
"use server";
import { redirect } from "next/navigation";
import React from "react";
interface WebPageProps {
@ -7,9 +8,10 @@ interface WebPageProps {
}
const WebPage: React.FC<WebPageProps> = () => {
redirect("/building");
return (
<div>
<h1>Web Page</h1>
<h1>Going to go to Evyos</h1>
</div>
);
};

View File

@ -1,12 +1,15 @@
"use server";
import React from "react";
import MainBodyWithHeader from "@/components/defaultLayout/MainBodyWithHeader";
import BuildingPage from "@/pages/Build/BuildingPage";
import DecisionBookPage from "@/pages/DecisionBook/DecisionBookPage";
const Decision = async () => {
return (
<div className="overflow-hidden">
<MainBodyWithHeader children={BuildingPage} section="BuildingPage" />
<MainBodyWithHeader
children={DecisionBookPage}
section="DecisionBookPage"
/>
</div>
);
};

View File

@ -0,0 +1,14 @@
"use server";
import React from "react";
import MainBodyWithHeader from "@/components/defaultLayout/MainBodyWithHeader";
import ProjectsPage from "@/pages/DecisionBook/ProjectsPage";
const Projects = async () => {
return (
<div className="overflow-hidden">
<MainBodyWithHeader children={ProjectsPage} section="ProjectsPage" />
</div>
);
};
export default Projects;

View File

@ -1,10 +1,11 @@
import React from "react";
import MainBodyWithHeader from "@/components/defaultLayout/MainBodyWithHeader";
import MeetingsPage from "@/pages/Meetings/MeetingsPage";
const Meetings = async () => {
return (
<div className="overflow-hidden">
<MainBodyWithHeader children={<></>} section="IdentitiesPage" />
<MainBodyWithHeader children={MeetingsPage} section="MeetingsPage" />
</div>
);
};

View File

@ -1,15 +1,16 @@
"use server";
import React from "react";
interface MainPageProps {
lang: string;
RenderPage: any;
section?: string;
section: MainPageProps;
}
const MainPage: React.FC<MainPageProps> = async ({
lang,
section,
RenderPage,
section,
}) => {
return <RenderPage lang={lang} section={section} />;
};

View File

@ -6,10 +6,11 @@ import Header from "./Header";
import MainPage from "@/components/commons/MainPage";
import { checkServerPageAvaliable } from "@/hooks/serverCheckPageAvailable";
import { MainPageProps } from "@/schemas/mainPage";
interface MainBodyWithHeaderProps {
children: any;
section?: string;
section: MainPageProps;
}
const MainBodyWithHeader: React.FC<MainBodyWithHeaderProps> = async ({
@ -25,7 +26,7 @@ const MainBodyWithHeader: React.FC<MainBodyWithHeaderProps> = async ({
<SideMenuProfile profileInfo={user} />
</div>
<div className="basis-3/4 p-4 border-2 border-black">
<SideMenu activeSection={section ? section : "building"} />
<SideMenu section={section} lang={user?.lang ?? "tr"} />
</div>
</div>
</Suspense>
@ -35,9 +36,9 @@ const MainBodyWithHeader: React.FC<MainBodyWithHeaderProps> = async ({
</div>
<main className="p-6">
<MainPage
section={section as any}
lang={user?.lang ?? "tr"}
RenderPage={children}
section={section}
/>
</main>
</div>

View File

@ -1,29 +1,236 @@
"use server";
import React from "react";
import Link from "next/link";
import { PagesInfosAndEndpoints } from "@/apimaps/mappingApi";
import { getIconByName } from "@/Icons/icons";
import { MainPageProps } from "@/schemas/mainPage";
import { getThreeLayerByPageName } from "@/lib/getPageFromMappings";
import { LanguagesSelectable } from "@/apimaps/mappingApi";
import { checkEndpointAvailability } from "@/apimaps/mappingApiFunctions";
interface SideMenuPropsInterface {
activeSection?: string;
interface SideMenuProps {
lang: string;
section: MainPageProps;
}
const SideMenu: React.FC<SideMenuPropsInterface> = ({ activeSection }) => {
const section = activeSection || "";
const SideMenu: React.FC<SideMenuProps> = async ({ section, lang }) => {
const { layer, currentPage, firstLayer, secondLayer, thirdLayer } = section;
const pages = getThreeLayerByPageName({
lang,
layer,
firstLayer,
secondLayer,
thirdLayer,
});
const firstLayerPage = pages?.firstLayer;
const secondLayerPage = pages?.secondLayer;
const thirdLayerPage = pages?.thirdLayer;
const language = lang as LanguagesSelectable;
if (layer === 1) {
return (
<nav className="flex flex-col text-sm">
{PagesInfosAndEndpoints.map((page) => {
const isActive = page.name === currentPage;
const Icon = getIconByName(page.icon);
if (isActive) {
return (
<div>
<nav className="flex flex-col">
{section === "building" ? (
<a href="/building" className="w-full p-4 bg-gray-100">
Building
</a>
) : (
<span className="w-full p-4 bg-gray-500">Building</span>
)}
<a href="/profile" className="w-full p-4 hover:bg-gray-300">
Profile
</a>
</nav>
<Link
href={page.url}
className={`px-10 border-gray-100 rounded-xl border-2 m-1 select-none pointer-events-none drag w-full p-4 flex items-center gap-2 "bg-gray-700 `}
>
<Icon />
{page.title?.[lang as LanguagesSelectable]}
</Link>
<div className="mb-6 mt-3 px-4">
{secondLayerPage.map((subPage: any) => {
const SubIcon = getIconByName(subPage.icon);
return (
<Link
key={subPage.name}
href={subPage.url}
className={`w-full p-4 my-3 rounded-2xl m-1 flex items-center gap-2 bg-slate-300 hover:bg-slate-500`}
>
<SubIcon />
{subPage.title?.[lang as LanguagesSelectable]}
</Link>
);
})}
</div>
</div>
);
} else {
return (
<div>
<Link
href={page.url}
className={`w-full p-4 rounded-xl m-1 flex items-center gap-2 bg-gray-100 hover:bg-gray-300`}
>
<Icon />
{page.title?.[lang as LanguagesSelectable]}
</Link>
</div>
);
}
})}
</nav>
);
} else if (layer === 2) {
return (
<nav className="flex flex-col text-sm">
{PagesInfosAndEndpoints.map((page) => {
const isActive = firstLayerPage.name === page.name;
const Icon = getIconByName(page.icon);
if (isActive) {
return (
<div>
<Link
href={page.url}
className={`w-full p-4 rounded-xl m-1 flex items-center gap-2 bg-gray-100 hover:bg-gray-300`}
>
<Icon />
{page.title?.[lang as LanguagesSelectable]}
</Link>
<div className="mb-6 mt-3 px-4">
{secondLayerPage.map((subPage: any) => {
const SubIcon = getIconByName(subPage.icon);
const isActive = subPage.name === currentPage;
if (isActive) {
return (
<Link
key={subPage.name}
href={subPage.url}
className={`px-10 border-gray-100 rounded-xl border-2 m-1 select-none pointer-events-none drag w-full p-4 flex items-center gap-2 "bg-gray-700 `}
>
<SubIcon />
{subPage.title?.[lang as LanguagesSelectable]}
</Link>
);
} else {
return (
<Link
key={subPage.name}
href={subPage.url}
className={`w-full p-4 my-3 rounded-2xl m-1 flex items-center gap-2 bg-slate-300 hover:bg-slate-500`}
>
<SubIcon />
{subPage.title?.[lang as LanguagesSelectable]}
</Link>
);
}
})}
</div>
</div>
);
} else {
return (
<div>
<Link
href={page.url}
className={`w-full p-4 rounded-xl m-1 flex items-center gap-2 bg-gray-100 hover:bg-gray-300`}
>
<Icon />
{page.title?.[lang as LanguagesSelectable]}
</Link>
</div>
);
}
})}
</nav>
);
} else if (layer === 3) {
return (
<nav className="flex flex-col text-sm">
{PagesInfosAndEndpoints.map((page) => {
const Icon = getIconByName(page.icon);
if (firstLayerPage.name === page.name) {
return (
<div>
<Link
href={page.url}
className={`w-full p-4 rounded-xl m-1 flex items-center gap-2 bg-gray-100 hover:bg-gray-300`}
>
<Icon />
{page.title?.[language]}
</Link>
<div className="mb-6 mt-3 px-4">
{secondLayerPage.map((subPage: any) => {
const SubIcon = getIconByName(subPage.icon);
if (subPage.name === secondLayerPage.name) {
return (
<div>
<Link
key={subPage.name}
href={subPage.url}
className={`w-full p-4 rounded-xl m-1 flex items-center gap-2 bg-gray-100 hover:bg-gray-300`}
>
<SubIcon />
{subPage.title?.[language]}
</Link>
<div className="mb-6 mt-3 px-4">
{thirdLayerPage.map((thirdPage: any) => {
const ThirdIcon = getIconByName(thirdPage.icon);
if (thirdPage.name === thirdLayerPage.name) {
return (
<Link
key={thirdPage.name}
href={thirdPage.url}
className={`px-10 border-gray-100 rounded-xl border-2 m-1 select-none pointer-events-none drag w-full p-4 flex items-center gap-2 "bg-gray-700 `}
>
<ThirdIcon />
{thirdPage.title?.[language]}
</Link>
);
} else {
return (
<Link
key={thirdPage.name}
href={thirdPage.url}
className={`w-full p-4 my-3 rounded-2xl m-1 flex items-center gap-2 bg-slate-300 hover:bg-slate-500`}
>
<ThirdIcon />
{thirdPage.title?.[language]}
</Link>
);
}
})}
</div>
</div>
);
} else {
return (
<Link
key={subPage.name}
href={subPage.url}
className={`w-full p-4 my-3 rounded-2xl m-1 flex items-center gap-2 bg-slate-300 hover:bg-slate-500`}
>
<SubIcon />
{subPage.title?.[language]}
</Link>
);
}
})}
</div>
</div>
);
} else {
return (
<div>
<Link
href={page.url}
className={`w-full p-4 rounded-xl m-1 flex items-center gap-2 bg-gray-100 hover:bg-gray-300`}
>
<Icon />
{page.title?.[language]}
</Link>
</div>
);
}
})}
</nav>
);
}
};
export default SideMenu;

View File

@ -48,7 +48,10 @@ async function initializePageContent(
new Error("Language not available");
}
const pageContent = retrievePageInfoByComponentName(pageName, user?.lang);
const pageContent = retrievePageInfoByComponentName(
pageName,
user?.lang as string
);
if (!Array.isArray(pageContent)) return;
await Promise.all(
Object.entries(MappingBuild).map(async ([endpoint, mapper]) => {

View File

@ -8,8 +8,9 @@ const retrievePageContent = (
lang: keyof LanguagesInterface
) => {
return (
PagesInfosAndEndpoints.find((page) => page.component === pageName)
?.pageInfo?.[lang] || null
PagesInfosAndEndpoints.find((page) => page.name === pageName)?.pageInfo?.[
lang
] || null
);
};

View File

@ -36,4 +36,28 @@ const retrievePageInfoByComponentName = (
return null;
};
export { retrievePageInfoByComponentName };
const retrievePageByComponentName = (componentName: string, lang: string) => {
const searchInCategory = (category: any): any => {
if (category.name === componentName) {
return category;
}
if (category.subCategories) {
for (const subCategory in category.subCategories) {
const result = searchInCategory(category.subCategories[subCategory]);
if (result) {
return result;
}
}
}
};
for (const category in PagesInfosAndEndpoints) {
const result = searchInCategory(PagesInfosAndEndpoints[category]);
if (result) {
return result;
}
}
return null;
};
export { retrievePageInfoByComponentName, retrievePageByComponentName };

View File

@ -0,0 +1,59 @@
import { retrievePageByComponentName } from "@/hooks/retrievePageInfoByComponentName";
function getSubCategoryByPageName(subCategories: [], layerName: string) {
console.log("subCategories", subCategories, "layerName", layerName);
const subCategory = subCategories.filter((s: any) => s.name === layerName);
console.log("subCategory", subCategory);
if (subCategory.length === 0) {
return null;
}
}
export function getThreeLayerByPageName({
lang,
layer = 1,
firstLayer,
secondLayer,
thirdLayer,
}: {
lang: string;
layer?: number;
firstLayer: string;
secondLayer?: string | null;
thirdLayer?: string | null;
}) {
if (layer === 1) {
const firstLayerpage = retrievePageByComponentName(firstLayer, lang);
return {
firstLayer: firstLayerpage,
secondLayer: firstLayerpage?.subCategories || null,
thirdLayer: null,
layer: 1,
};
} else if (layer === 2) {
const firstLayerpage = retrievePageByComponentName(firstLayer, lang);
const secondLayerPage = retrievePageByComponentName(
secondLayer || "",
lang
);
return {
firstLayer: firstLayerpage,
secondLayer: firstLayerpage?.subCategories || null,
thirdLayer: secondLayerPage?.subCategories || null,
layer: 2,
};
} else if (layer === 3) {
const firstLayerpage = retrievePageByComponentName(firstLayer, lang);
const secondLayerPage = retrievePageByComponentName(
secondLayer || "",
lang
);
const thirdLayerPage = retrievePageByComponentName(thirdLayer || "", lang);
return {
firstLayer: firstLayerpage,
secondLayer: secondLayerPage,
thirdLayer: thirdLayerPage,
layer: 3,
};
}
}

View File

@ -0,0 +1,59 @@
"use server";
import React, { Suspense } from "react";
import Link from "next/link";
import { PlusCircle } from "lucide-react";
import { checkEndpointsAvailable } from "@/hooks/checkpageAvaliable";
import { retrieveHeadersAndValidationByEndpoint } from "@/apicalls/validations/validations";
import { TableComponent } from "@/components/commons/Table";
import { PagePropsInterface } from "@/schemas/PageSchema";
const AccessibilitiesPage: React.FC<PagePropsInterface> = async ({
lang,
section,
}) => {
const pageEndpoint = "/account/records/list";
const availablePageContent = await checkEndpointsAvailable({
section: section as string,
lang,
});
const tableValidateAndHeaders = await retrieveHeadersAndValidationByEndpoint({
endpoint: pageEndpoint,
});
return (
<div>
<Suspense fallback={<div>Accessibilities Page is Loading...</div>}>
<h1 className="mt-8 text-center">
{availablePageContent?.table?.title}
</h1>
<h1 className="mt-4 text-center">
{availablePageContent?.table?.description}
</h1>
<div className="my-6">
{availablePageContent?.create && (
<Link
href={"/account/records/create"}
className="flex items-center justify-center gap-2 px-4 py-2 bg-slate-500 text-white rounded hover:bg-slate-700"
>
<PlusCircle size={16} />
Create
</Link>
)}
</div>
<div className="overflow-x-scroll my-6">
{availablePageContent?.table && (
<TableComponent
pageContent={availablePageContent}
tableValidateAndHeaders={tableValidateAndHeaders}
apiFunction={() => console.log("apiFunction")}
redirectTo="/building/update"
/>
)}
</div>
</Suspense>
</div>
);
};
export default AccessibilitiesPage;

View File

@ -0,0 +1,64 @@
"use server";
import React, { Suspense } from "react";
import Link from "next/link";
import { PlusCircle } from "lucide-react";
import { checkEndpointsAvailable } from "@/hooks/checkpageAvaliable";
import { retrieveBuildList } from "@/apicalls/building/build";
import { retrieveHeadersAndValidationByEndpoint } from "@/apicalls/validations/validations";
import { TableComponent } from "@/components/commons/Table";
import { PagePropsInterface } from "@/schemas/PageSchema";
import UserIsNotAuthorized from "@/pages/OnConstruction/UserIsNotAuthorized";
const LivingSpacePage: React.FC<PagePropsInterface> = async ({
lang,
section,
}) => {
const pageEndpoint = "building/build/list";
const availablePageContent = await checkEndpointsAvailable({
section: section as string,
lang,
});
const tableValidateAndHeaders = await retrieveHeadersAndValidationByEndpoint({
endpoint: pageEndpoint,
});
if (!tableValidateAndHeaders?.validated || !availablePageContent?.table) {
return <UserIsNotAuthorized />;
}
return (
<div>
<Suspense fallback={<div>Building Page is Loading...</div>}>
<h1 className="mt-8 text-center">
{availablePageContent?.table?.title}
</h1>
<h1 className="mt-4 text-center">
{availablePageContent?.table?.description}
</h1>
<div className="my-6">
{availablePageContent?.create && (
<Link
href={"/building/create"}
className="flex items-center justify-center gap-2 px-4 py-2 bg-slate-500 text-white rounded hover:bg-slate-700"
>
<PlusCircle size={16} />
Create
</Link>
)}
</div>
<div className="overflow-x-scroll my-6">
{availablePageContent?.table && (
<TableComponent
pageContent={availablePageContent}
tableValidateAndHeaders={tableValidateAndHeaders}
apiFunction={retrieveBuildList}
redirectTo="/building/update"
/>
)}
</div>
</Suspense>
</div>
);
};
export default LivingSpacePage;

View File

@ -0,0 +1,65 @@
"use server";
import React, { Suspense } from "react";
import Link from "next/link";
import { PlusCircle } from "lucide-react";
import { checkEndpointsAvailable } from "@/hooks/checkpageAvaliable";
import { retrieveBuildList } from "@/apicalls/building/build";
import { retrieveHeadersAndValidationByEndpoint } from "@/apicalls/validations/validations";
import { TableComponent } from "@/components/commons/Table";
import { PagePropsInterface } from "@/schemas/PageSchema";
import UserIsNotAuthorized from "@/pages/OnConstruction/UserIsNotAuthorized";
const BuildingAreaPage: React.FC<PagePropsInterface> = async ({
lang,
section,
}) => {
const pageEndpoint = "/building/area/list";
const availablePageContent = await checkEndpointsAvailable({
section: section as string,
lang,
});
const tableValidateAndHeaders = await retrieveHeadersAndValidationByEndpoint({
endpoint: pageEndpoint,
});
if (!tableValidateAndHeaders?.validated || !availablePageContent?.table) {
return <UserIsNotAuthorized />;
}
return (
<div>
<Suspense fallback={<div>Building Page is Loading...</div>}>
<h1 className="mt-8 text-center">
{availablePageContent?.table?.title}
</h1>
<h1 className="mt-4 text-center">
{availablePageContent?.table?.description}
</h1>
<div className="my-6">
{availablePageContent?.create && (
<Link
href={"/building/create"}
className="flex items-center justify-center gap-2 px-4 py-2 bg-slate-500 text-white rounded hover:bg-slate-700"
>
<PlusCircle size={16} />
Create
</Link>
)}
</div>
<div className="overflow-x-scroll my-6">
{availablePageContent?.table && (
<TableComponent
pageContent={availablePageContent}
tableValidateAndHeaders={tableValidateAndHeaders}
apiFunction={retrieveBuildList}
redirectTo="/building/update"
/>
)}
</div>
</Suspense>
</div>
);
};
export default BuildingAreaPage;

View File

@ -1,6 +1,7 @@
"use server";
import React, { Suspense } from "react";
import Link from "next/link";
import UserIsNotAuthorized from "@/pages/OnConstruction/UserIsNotAuthorized";
import { PlusCircle } from "lucide-react";
import { checkEndpointsAvailable } from "@/hooks/checkpageAvaliable";
@ -15,12 +16,15 @@ const BuildingPage: React.FC<PagePropsInterface> = async ({
}) => {
const pageEndpoint = "building/build/list";
const availablePageContent = await checkEndpointsAvailable({
section: section as string,
section: section?.currentPage || "",
lang,
});
const tableValidateAndHeaders = await retrieveHeadersAndValidationByEndpoint({
endpoint: pageEndpoint,
});
if (!tableValidateAndHeaders?.validated || !availablePageContent?.table) {
return <UserIsNotAuthorized />;
}
return (
<div>

View File

@ -0,0 +1,64 @@
"use server";
import React, { Suspense } from "react";
import Link from "next/link";
import { PlusCircle } from "lucide-react";
import { checkEndpointsAvailable } from "@/hooks/checkpageAvaliable";
import { retrieveBuildList } from "@/apicalls/building/build";
import { retrieveHeadersAndValidationByEndpoint } from "@/apicalls/validations/validations";
import { TableComponent } from "@/components/commons/Table";
import { PagePropsInterface } from "@/schemas/PageSchema";
import UserIsNotAuthorized from "@/pages/OnConstruction/UserIsNotAuthorized";
const BuildingPartPage: React.FC<PagePropsInterface> = async ({
lang,
section,
}) => {
const pageEndpoint = "building/build/list";
const availablePageContent = await checkEndpointsAvailable({
section: section?.currentPage as string,
lang,
});
const tableValidateAndHeaders = await retrieveHeadersAndValidationByEndpoint({
endpoint: pageEndpoint,
});
if (!tableValidateAndHeaders?.validated || !availablePageContent?.table) {
return <UserIsNotAuthorized />;
}
return (
<div>
<Suspense fallback={<div>Building Page is Loading...</div>}>
<h1 className="mt-8 text-center">
{availablePageContent?.table?.title}
</h1>
<h1 className="mt-4 text-center">
{availablePageContent?.table?.description}
</h1>
<div className="my-6">
{availablePageContent?.create && (
<Link
href={"/building/create"}
className="flex items-center justify-center gap-2 px-4 py-2 bg-slate-500 text-white rounded hover:bg-slate-700"
>
<PlusCircle size={16} />
Create
</Link>
)}
</div>
<div className="overflow-x-scroll my-6">
{availablePageContent?.table && (
<TableComponent
pageContent={availablePageContent}
tableValidateAndHeaders={tableValidateAndHeaders}
apiFunction={retrieveBuildList}
redirectTo="/building/update"
/>
)}
</div>
</Suspense>
</div>
);
};
export default BuildingPartPage;

View File

@ -0,0 +1,59 @@
"use server";
import React, { Suspense } from "react";
import Link from "next/link";
import { PlusCircle } from "lucide-react";
import { checkEndpointsAvailable } from "@/hooks/checkpageAvaliable";
import { retrieveHeadersAndValidationByEndpoint } from "@/apicalls/validations/validations";
import { TableComponent } from "@/components/commons/Table";
import { PagePropsInterface } from "@/schemas/PageSchema";
const CompaniesPage: React.FC<PagePropsInterface> = async ({
lang,
section,
}) => {
const pageEndpoint = "/account/records/list";
const availablePageContent = await checkEndpointsAvailable({
section: section as string,
lang,
});
const tableValidateAndHeaders = await retrieveHeadersAndValidationByEndpoint({
endpoint: pageEndpoint,
});
return (
<div>
<Suspense fallback={<div>Account Page is Loading...</div>}>
<h1 className="mt-8 text-center">
{availablePageContent?.table?.title}
</h1>
<h1 className="mt-4 text-center">
{availablePageContent?.table?.description}
</h1>
<div className="my-6">
{availablePageContent?.create && (
<Link
href={"/account/records/create"}
className="flex items-center justify-center gap-2 px-4 py-2 bg-slate-500 text-white rounded hover:bg-slate-700"
>
<PlusCircle size={16} />
Create
</Link>
)}
</div>
<div className="overflow-x-scroll my-6">
{availablePageContent?.table && (
<TableComponent
pageContent={availablePageContent}
tableValidateAndHeaders={tableValidateAndHeaders}
apiFunction={() => console.log("apiFunction")}
redirectTo="/building/update"
/>
)}
</div>
</Suspense>
</div>
);
};
export default CompaniesPage;

View File

@ -0,0 +1,60 @@
"use server";
import React, { Suspense } from "react";
import Link from "next/link";
import { PlusCircle } from "lucide-react";
import { checkEndpointsAvailable } from "@/hooks/checkpageAvaliable";
import { retrieveHeadersAndValidationByEndpoint } from "@/apicalls/validations/validations";
import { TableComponent } from "@/components/commons/Table";
import { PagePropsInterface } from "@/schemas/PageSchema";
import { retrieveBuildList } from "@/apicalls/building/build";
const DecisionBookPage: React.FC<PagePropsInterface> = async ({
lang,
section,
}) => {
const pageEndpoint = "/account/records/list";
const availablePageContent = await checkEndpointsAvailable({
section: section as string,
lang,
});
const tableValidateAndHeaders = await retrieveHeadersAndValidationByEndpoint({
endpoint: pageEndpoint,
});
return (
<div>
<Suspense fallback={<div>Account Page is Loading...</div>}>
<h1 className="mt-8 text-center">
{availablePageContent?.table?.title}
</h1>
<h1 className="mt-4 text-center">
{availablePageContent?.table?.description}
</h1>
<div className="my-6">
{availablePageContent?.create && (
<Link
href={"/account/records/create"}
className="flex items-center justify-center gap-2 px-4 py-2 bg-slate-500 text-white rounded hover:bg-slate-700"
>
<PlusCircle size={16} />
Create
</Link>
)}
</div>
<div className="overflow-x-scroll my-6">
{availablePageContent?.table && (
<TableComponent
pageContent={availablePageContent}
tableValidateAndHeaders={tableValidateAndHeaders}
apiFunction={retrieveBuildList}
redirectTo="/building/update"
/>
)}
</div>
</Suspense>
</div>
);
};
export default DecisionBookPage;

View File

@ -0,0 +1,60 @@
"use server";
import React, { Suspense } from "react";
import Link from "next/link";
import { PlusCircle } from "lucide-react";
import { checkEndpointsAvailable } from "@/hooks/checkpageAvaliable";
import { retrieveHeadersAndValidationByEndpoint } from "@/apicalls/validations/validations";
import { TableComponent } from "@/components/commons/Table";
import { PagePropsInterface } from "@/schemas/PageSchema";
import { retrieveBuildList } from "@/apicalls/building/build";
const ProjectsPage: React.FC<PagePropsInterface> = async ({
lang,
section,
}) => {
const pageEndpoint = "/account/records/list";
const availablePageContent = await checkEndpointsAvailable({
section: section as string,
lang,
});
const tableValidateAndHeaders = await retrieveHeadersAndValidationByEndpoint({
endpoint: pageEndpoint,
});
return (
<div>
<Suspense fallback={<div>Account Page is Loading...</div>}>
<h1 className="mt-8 text-center">
{availablePageContent?.table?.title}
</h1>
<h1 className="mt-4 text-center">
{availablePageContent?.table?.description}
</h1>
<div className="my-6">
{availablePageContent?.create && (
<Link
href={"/account/records/create"}
className="flex items-center justify-center gap-2 px-4 py-2 bg-slate-500 text-white rounded hover:bg-slate-700"
>
<PlusCircle size={16} />
Create
</Link>
)}
</div>
<div className="overflow-x-scroll my-6">
{availablePageContent?.table && (
<TableComponent
pageContent={availablePageContent}
tableValidateAndHeaders={tableValidateAndHeaders}
apiFunction={retrieveBuildList}
redirectTo="/building/update"
/>
)}
</div>
</Suspense>
</div>
);
};
export default ProjectsPage;

View File

@ -0,0 +1,15 @@
import React from "react";
const OnConstructionPage: React.FC<any> = async () => {
return (
<div className={""}>
<div className={""}>
<h1>🚧 Under Construction 🚧</h1>
<p>We're working hard to bring you something amazing!</p>
<p>Please check back soon.</p>
</div>
</div>
);
};
export default OnConstructionPage;

View File

@ -0,0 +1,31 @@
"use server";
import React from "react";
import Link from "next/link";
const UserIsNotAuthorized: React.FC = () => {
return (
<div className="flex flex-col items-center justify-center min-h-screen bg-gray-100">
<div className="text-center p-8 bg-white rounded-lg shadow-md">
<h1 className="text-4xl font-bold text-red-600 mb-4">
Unauthorized Access
</h1>
<div className="text-gray-600 mb-6">
<p className="mb-2">
Sorry, you don't have permission to access this content.
</p>
<p>
Please contact your administrator if you believe this is a mistake.
</p>
</div>
<Link
href="/dashboard"
className="inline-block px-6 py-2 bg-slate-600 text-white rounded hover:bg-blue-700 transition-colors"
>
Go to dashboard
</Link>
</div>
</div>
);
};
export default UserIsNotAuthorized;

View File

@ -1,6 +1,8 @@
import { MainPageProps } from "./mainPage";
interface PagePropsInterface {
lang: string;
section?: string;
section?: MainPageProps;
}
export type { PagePropsInterface };

9
src/schemas/mainPage.ts Normal file
View File

@ -0,0 +1,9 @@
interface MainPageProps {
layer: number;
currentPage: string;
firstLayer: string;
secondLayer: string | null;
thirdLayer: string | null;
}
export type { MainPageProps };