updated app reachable codes

This commit is contained in:
2025-04-09 11:51:28 +03:00
parent 7eadadbd1d
commit 7c2150a8b0
23 changed files with 1040 additions and 187 deletions

View File

@@ -0,0 +1,104 @@
"use server";
import React from "react";
import { Home, User, Settings, Mail, Calendar } from "lucide-react";
import { transformMenu, LanguageTranslation } from "@/components/menu/runner";
import Link from "next/link";
async function LeftMenu({
searchParams,
pageUuidList,
lang,
}: {
pageUuidList: string[];
lang: keyof LanguageTranslation;
searchParams: { [key: string]: string | string[] | undefined };
}) {
const transformedMenu = transformMenu(pageUuidList);
// Get the menuContext from searchParams without setting a default value
const menuContext = searchParams?.menu;
// Only parse the indices if menuContext exists
let firstLayerIndex = -1;
let secondLayerIndex = -1;
if (menuContext) {
const indices = menuContext.toString().split("*").map(Number);
firstLayerIndex = indices[0] || 0;
secondLayerIndex = indices[1] || 0;
}
const pageSelected = searchParams?.page;
return (
<div>
<nav className="flex flex-col space-y-2">
<div className="text-xl font-bold mb-6 text-center">Dashboard</div>
{transformedMenu.map((item, firstIndex) => (
<div key={item.name} className="mb-4">
<Link
href={`/dashboard?${
pageSelected ? `page=${pageSelected}` : ""
}&menu=${firstIndex}*0`}
className={`text-xl font-semibold pl-5 my-2 py-2 block ${
firstIndex === firstLayerIndex
? "text-emerald-600"
: "text-emerald-400"
} hover:text-emerald-600`}
>
{item.lg[lang]}
</Link>
{/* Only render the second layer if menuContext exists and this first layer item is selected */}
{menuContext && firstIndex === firstLayerIndex && (
<ul className="space-y-2">
{item.subList.map((subItem, secondIndex) => (
<div key={subItem.name}>
<Link
href={`/dashboard?${
pageSelected ? `page=${pageSelected}` : ""
}&menu=${firstIndex}*${secondIndex}`}
className={`ml-5 my-4 pl-4 text-xl font-semibold block ${
secondIndex === secondLayerIndex
? "text-emerald-700"
: "text-emerald-500"
} hover:text-emerald-700`}
>
{subItem.lg[lang]}
</Link>
{/* Only render the third layer if this second layer item is selected */}
{firstIndex === firstLayerIndex &&
secondIndex === secondLayerIndex && (
<div className="ml-5">
{subItem.subList.map((subSubItem) => (
<Link
key={subSubItem.appUUID}
href={`/dashboard?page=${subSubItem.appUUID}&menu=${firstIndex}*${secondIndex}`}
className={`flex flex-row text-xl py-4 my-4 w-full space-x-2 p-2 rounded ${
pageSelected === subSubItem.appUUID
? " bg-gray-100 cursor-not-allowed"
: "hover:bg-gray-200"
}`}
>
<span className="text-gray-400">
<Home />
</span>
<span className="ml-5 text-gray-700">
{subSubItem.lg[lang]}
</span>
</Link>
))}
</div>
)}
</div>
))}
</ul>
)}
</div>
))}
</nav>
</div>
);
}
export default LeftMenu;

View File

@@ -0,0 +1,32 @@
import React from "react";
import retrievePage from "@/components/NavigatePages";
function MainPage({
pageSelected,
lang,
}: {
pageSelected: string | undefined;
lang: string;
}) {
const ComponentPage = retrievePage({
pageId: pageSelected ?? "",
});
if (!ComponentPage) {
return (
<div className="flex flex-col w-full">
<h2 className="text-2xl font-semibold p-4">No Page Selected</h2>
</div>
);
}
return (
<>
{/* Main Content */}
<main className="flex-grow p-6 bg-gray-50 overflow-y-auto">
<ComponentPage lang={lang} />
</main>
</>
);
}
export default MainPage;

View File

@@ -2,13 +2,56 @@ import React from "react";
import { checkAccessTokenIsValid } from "@/apicalls/cookies/token";
import { redirect } from "next/navigation";
async function DashboardPage() {
const token_is_valid = await checkAccessTokenIsValid();
import LeftMenu from "./leftMenu";
import MainPage from "./main";
export default async function DashboardLayout({
searchParams,
}: {
searchParams: { [key: string]: string | undefined };
}) {
const token_is_valid = await checkAccessTokenIsValid();
if (!token_is_valid) {
redirect("/auth/login");
}
return <div>You have arrived to Dashboard Page</div>;
}
const pageUuidList = [
"6015129b-f665-479c-a440-04fb82ea6114",
"14a98ae7-c64e-403d-9b53-32e7ea867ab4",
"e368137d-d548-4ed4-90da-337bcc5d1559",
"d3d97973-41c6-4bad-881b-6bf77d837fa5",
]; // Mock data of pageUUID list []
const lang = "tr"; // Assuming you have a way to determine the current language
const queryParams = await searchParams;
const pageSelected = queryParams?.page || undefined;
export default DashboardPage;
return (
<div className="flex h-screen overflow-hidden">
{/* Sidebar */}
<aside className="w-1/4 border-r p-4 overflow-y-auto">
<LeftMenu
pageUuidList={pageUuidList}
lang={lang}
searchParams={queryParams}
/>
</aside>
{/* Main Content Area */}
<div className="flex flex-col w-3/4">
{/* Sticky Header */}
<header className="sticky top-0 bg-white shadow-md z-10 p-4 flex justify-between items-center">
<h1 className="text-2xl font-semibold">Dashboard</h1>
<div className="flex items-center space-x-4">
<input
type="text"
placeholder="Search..."
className="border px-3 py-2 rounded-lg"
/>
<div className="w-10 h-10 bg-gray-300 rounded-full"></div>
</div>
</header>
<MainPage pageSelected={pageSelected} lang={lang} />
</div>
</div>
);
}

View File

@@ -0,0 +1,41 @@
import { PageProps } from "./interFaces";
import Page0001 from "./page0001";
const PageIndexs = {
"6015129b-f665-479c-a440-04fb82ea6114": Page0001,
};
function UnAuthorizedPage({ lang }: PageProps) {
return (
<>
<div className="flex flex-col h-screen">
<header className="bg-gray-800 text-white p-4 text-center">
<h1 className="text-2xl font-bold">Unauthorized Access</h1>
</header>
<main className="flex-grow p-4 bg-gray-100">
<p className="text-gray-700">
You do not have permission to access this page.
</p>
<p className="text-gray-700">Please contact the administrator.</p>
</main>
<footer className="bg-gray-800 text-white p-4 text-center">
<p>&copy; 2023 My Application</p>
</footer>
</div>
</>
);
}
export function retrievePage({
pageId,
}: {
pageId: string;
}): React.ComponentType<PageProps> {
const PageComponent = PageIndexs[pageId as keyof typeof PageIndexs];
if (!PageComponent) {
return UnAuthorizedPage;
}
return PageComponent;
}
export default retrievePage;

View File

@@ -0,0 +1,3 @@
export interface PageProps {
lang: string;
}

View File

@@ -0,0 +1,36 @@
import React from "react";
import { PageProps } from "./interFaces";
const pageContext = {
tr: {
pageTitle: "Sayfa 0001",
pageDescription: "Bu, Sayfa 0001'in içeriğidir.",
},
en: {
pageTitle: "Page 0001",
pageDescription: "This is the content of Page 0001.",
},
};
function Page0001({ lang }: PageProps) {
const { pageTitle, pageDescription } =
pageContext[lang as keyof typeof pageContext];
return (
<>
<div className="flex flex-col h-screen">
<header className="bg-gray-800 text-white p-4 text-center">
<h1 className="text-2xl font-bold">{pageTitle}</h1>
</header>
<main className="flex-grow p-4 bg-gray-100">
<p className="text-gray-700">{pageDescription}</p>
</main>
<footer className="bg-gray-800 text-white p-4 text-center">
<p>&copy; 2023 My Application</p>
</footer>
</div>
</>
);
}
export default Page0001;

View File

@@ -0,0 +1,125 @@
/**
* Filters the menu structure based on intersections with provided UUIDs
* @param {string[]} uuids - Array of UUIDs to check for intersection
* @param {Array} menu - The original menu structure
* @returns {Array} - Filtered menu structure with only matching items
*/
import Menu from "@/menu/store"; // Assuming you have a menu structure imported
// Define TypeScript interfaces for menu structure
interface LanguageTranslation {
tr: string;
en: string;
}
interface MenuThirdLevel {
name: string;
lg: LanguageTranslation;
appList: string[];
}
interface MenuSecondLevel {
name: string;
lg: LanguageTranslation;
subList: MenuThirdLevel[];
}
interface MenuFirstLevel {
name: string;
lg: LanguageTranslation;
subList: MenuSecondLevel[];
}
// Define interfaces for the filtered menu structure
interface FilteredMenuThirdLevel {
name: string;
lg: LanguageTranslation;
appUUID: string;
}
interface FilteredMenuSecondLevel {
name: string;
lg: LanguageTranslation;
subList: FilteredMenuThirdLevel[];
}
interface FilteredMenuFirstLevel {
name: string;
lg: LanguageTranslation;
subList: FilteredMenuSecondLevel[];
}
export type { LanguageTranslation };
function transformMenu(uuids: string[]) {
// Helper function to check if arrays have at least one common element
const hasIntersection = (array1: string[], array2: string[]): boolean => {
return array1.some((item) => array2.includes(item));
};
// Process the menu structure
const filteredMenu: FilteredMenuFirstLevel[] = Menu.reduce(
(acc: FilteredMenuFirstLevel[], firstLevel: MenuFirstLevel) => {
// Create a new first level item with empty subList
const newFirstLevel: FilteredMenuFirstLevel = {
name: firstLevel.name,
lg: { ...firstLevel.lg },
subList: [],
};
// Process second level items
firstLevel.subList.forEach((secondLevel: MenuSecondLevel) => {
// Create a new second level item with empty subList
const newSecondLevel: FilteredMenuSecondLevel = {
name: secondLevel.name,
lg: { ...secondLevel.lg },
subList: [],
};
// Process third level items
secondLevel.subList.forEach((thirdLevel: MenuThirdLevel) => {
// Check if the third level's appList has an intersection with our UUIDs
if (
thirdLevel.appList &&
hasIntersection(thirdLevel.appList, uuids)
) {
// Find the first matching UUID
const matchedUUID = thirdLevel.appList.find((uuid) =>
uuids.includes(uuid)
);
// Only proceed if we found a matching UUID (should always be true due to hasIntersection)
if (matchedUUID) {
// Create a modified third level item with the matched UUID
const newThirdLevel: FilteredMenuThirdLevel = {
name: thirdLevel.name,
lg: { ...thirdLevel.lg },
appUUID: matchedUUID,
};
// Add the modified third level to the second level's subList
newSecondLevel.subList.push(newThirdLevel);
}
}
});
// Only add the second level to the first level if it has any matching third level items
if (newSecondLevel.subList.length > 0) {
newFirstLevel.subList.push(newSecondLevel);
}
});
// Only add the first level to the result if it has any matching second level items
if (newFirstLevel.subList.length > 0) {
acc.push(newFirstLevel);
}
return acc;
},
[]
);
return filteredMenu;
}
export { transformMenu };

View File

@@ -0,0 +1,180 @@
const Individual = {
name: "Individual",
lg: {
tr: "Birey",
en: "Individual",
},
appList: [
"0362071d-90d9-48db-8fa0-3528aaf450bd",
"6015129b-f665-479c-a440-04fb82ea6114",
],
};
const User = {
name: "User",
lg: {
tr: "Kullanıcı",
en: "User",
},
appList: ["14a98ae7-c64e-403d-9b53-32e7ea867ab4"],
};
const Build = {
name: "Build",
lg: {
tr: "Apartman",
en: "Build",
},
appList: ["e368137d-d548-4ed4-90da-337bcc5d1559"],
};
const BuildParts = {
name: "BuildParts",
lg: {
tr: "Daire",
en: "BuildParts",
},
appList: [],
};
const BuildArea = {
name: "BuildArea",
lg: {
tr: "Daire",
en: "BuildArea",
},
appList: [],
};
const ManagementAccounting = {
name: "ManagementAccounting",
lg: {
tr: "Yönetim Cari Hareketler",
en: "ManagementAccounting",
},
appList: [],
};
const ManagementBudget = {
name: "ManagementBudget",
lg: {
tr: "Yönetim Bütçe İşlemleri",
en: "Management Budget",
},
appList: [],
};
const BuildPartsAccounting = {
name: "BuildPartsAccounting",
lg: {
tr: "Daire Cari Hareketler",
en: "Build Parts Accounting",
},
appList: [],
};
const AnnualMeeting = {
name: "AnnualMeeting",
lg: {
tr: "Yıllık Olağan Toplantı Tanımlama ve Davet",
en: "Annual Meetings and Invitations",
},
appList: ["d3d97973-41c6-4bad-881b-6bf77d837fa5"],
};
const AnnualMeetingClose = {
name: "AnnualMeetingClose",
lg: {
tr: "Yıllık Olağan Toplantı kapatma ve Cari Yaratma",
en: "Annual Meeting Close and Accountings",
},
appList: [],
};
const EmergencyMeeting = {
name: "EmergencyMeeting",
lg: {
tr: "Acil Toplantı Tanımlama ve Davet",
en: "Emergency Meeting and Invitations",
},
appList: [],
};
const EmergencyMeetingClose = {
name: "EmergencyMeetingClose",
lg: {
tr: "Acil Olağan Toplantı kapatma ve Cari Yaratma",
en: "Emergency Meeting Close and Accountings",
},
appList: [],
};
const MeetingParticipations = {
name: "MeetingParticipations",
lg: {
tr: "Toplantı Katılım İşlemleri",
en: "Meeting Participations",
},
appList: ["SomeUUID"],
};
const Menu = [
{
name: "Definitions",
lg: {
tr: "Tanımlar",
en: "Definitions",
},
subList: [
{
name: "People",
lg: {
tr: "Kişiler",
en: "People",
},
subList: [Individual, User],
},
{
name: "Building",
lg: {
tr: "Binalar",
en: "Building",
},
subList: [Build, BuildParts, BuildArea],
},
],
},
{
name: "Building Management",
lg: {
tr: "Bina Yönetimi",
en: "Building Management",
},
subList: [
{
name: "Management Accounting",
lg: {
tr: "Cari işlemler",
en: "Management Accounting",
},
subList: [ManagementAccounting, ManagementBudget, BuildPartsAccounting],
},
{
name: "Meetings",
lg: {
tr: "Toplantılar",
en: "Meetings",
},
subList: [
AnnualMeeting,
AnnualMeetingClose,
EmergencyMeeting,
EmergencyMeetingClose,
MeetingParticipations,
],
},
],
},
];
export default Menu;