updated services web user selection

This commit is contained in:
2025-06-16 15:52:50 +03:00
parent 8573c8021b
commit b73417a625
14 changed files with 117 additions and 62 deletions

View File

@@ -8,6 +8,7 @@ import { NextResponse } from "next/server";
export async function GET() {
try {
const menu = await getMenuFromRedis();
console.log("menu", menu);
return NextResponse.json({
status: 200,
data: menu,

View File

@@ -1,5 +1,8 @@
import { NextResponse } from "next/server";
import { loginViaAccessKeys, initFirstSelection } from "@/fetchers/custom/login/login";
import {
loginViaAccessKeys,
initFirstSelection,
} from "@/fetchers/custom/login/login";
import { loginSchemaEmail } from "@/pages/single/auth/login/schemas";
export async function POST(req: Request): Promise<NextResponse> {
@@ -20,7 +23,11 @@ export async function POST(req: Request): Promise<NextResponse> {
}
const userLogin = await loginViaAccessKeys(dataValidated);
await initFirstSelection(userLogin.data?.firstSelection, userLogin.data?.userType);
console.log("userLogin", userLogin);
await initFirstSelection(
userLogin.data?.firstSelection,
userLogin.data?.userType
);
if (userLogin.status === 200 || userLogin.status === 202) {
return NextResponse.json({
status: 200,

View File

@@ -6,9 +6,10 @@ interface ClientSelectionSectionProps {
selectionData: any;
refreshSelection: () => Promise<void>;
updateSelection: (newSelection: any) => Promise<boolean>;
refreshMenu: () => Promise<void>;
}
const ClientSelectionSection: FC<ClientSelectionSectionProps> = ({ selectionData, refreshSelection, updateSelection }) => {
const ClientSelectionSection: FC<ClientSelectionSectionProps> = ({ selectionData, refreshSelection, updateSelection, refreshMenu }) => {
const [expandedBuilds, setExpandedBuilds] = useState<{ [key: string]: boolean }>({});
if (!selectionData || !selectionData.selectionList) { return null }
@@ -21,7 +22,7 @@ const ClientSelectionSection: FC<ClientSelectionSectionProps> = ({ selectionData
selectionData.selectionList.map((client: any, index: number) => {
return (
<div key={client.uu_id || client.id || `client-${index}`}>
{client && renderOneClientSelection({ item: client, selectedItem: selectionData.activeSelection, updateSelection, refreshSelection })}
{client && renderOneClientSelection({ item: client, selectedItem: selectionData.activeSelection, updateSelection, refreshSelection, refreshMenu })}
</div>
);
})
@@ -63,7 +64,7 @@ const ClientSelectionSection: FC<ClientSelectionSectionProps> = ({ selectionData
{buildData.occupants && Array.isArray(buildData.occupants) ? (
buildData.occupants.map((client: any, index: number) => (
<div key={client.occupant_uu_id || client.part_uu_id || `occupant-${index}`}>
{client && renderOneClientSelection({ item: client, selectedItem: selectionData.activeSelection, updateSelection, refreshSelection })}
{client && renderOneClientSelection({ item: client, selectedItem: selectionData.activeSelection, updateSelection, refreshSelection, refreshMenu })}
</div>
))
) : (<div>No occupants found</div>)}

View File

@@ -8,7 +8,7 @@ import ClientSelectionSection from "./clientSelectionSection";
import MenuItemsSection from "./menuItemsSection";
import MenuLoadingState from "./menuLoadingState";
import MenuErrorState from "./menuErrorState";
import MenuEmptyState from "./menuEmptyState";
import LoadingContent from "@/components/mutual/loader/component";
const MenuComponent: FC<MenuProps> = ({
@@ -20,8 +20,7 @@ const MenuComponent: FC<MenuProps> = ({
}) => {
if (menuLoading) { return <MenuLoadingState /> }
if (menuError) { return <MenuErrorState error={menuError} />; }
if (availableApplications.length === 0) { return <MenuEmptyState />; }
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)]">
@@ -32,7 +31,7 @@ const MenuComponent: FC<MenuProps> = ({
</Suspense>
{/* Client Selection Section */}
<Suspense fallback={<div><LoadingContent height="h-16" size="w-36 h-48" key={"loading-content"} plane="h-full w-full" /></div>}>
<ClientSelectionSection selectionData={selectionData} refreshSelection={refreshSelection} updateSelection={updateSelection} />
<ClientSelectionSection selectionData={selectionData} refreshSelection={refreshSelection} updateSelection={updateSelection} refreshMenu={refreshMenu} />
</Suspense>
{/* Menu Items Section */}
<Suspense fallback={<div><LoadingContent height="h-16" size="w-36 h-48" key={"loading-content"} plane="h-full w-full" /></div>}>

View File

@@ -11,7 +11,7 @@ import {
MenuStructure,
MenuItemsSectionProps,
} from "./types";
import MenuEmptyState from "./menuEmptyState";
const menuStaticTranslation = {
tr: { menu: "Menü" },
@@ -26,6 +26,7 @@ const MenuItemsSection: FC<MenuItemsSectionProps> = ({ availableApplications, ac
const [activeSecondLayer, setActiveSecondLayer] = useState<string | null>(null);
const [activeThirdLayer, setActiveThirdLayer] = useState<string | null>(null);
useEffect(() => {
const newMenuStructure: MenuStructure = {};
const menuTranslationWLang = menuTranslation[lang as keyof typeof menuTranslation];
@@ -82,6 +83,8 @@ const MenuItemsSection: FC<MenuItemsSectionProps> = ({ availableApplications, ac
};
const renderFirstLayerItems = () => {
return Object.entries(menuStructure).map(([firstLayerKey, secondLayerItems]) => {
const isActive = activeFirstLayer === firstLayerKey;
const isExpanded = expandedFirstLayer === firstLayerKey;
@@ -92,13 +95,35 @@ const MenuItemsSection: FC<MenuItemsSectionProps> = ({ availableApplications, ac
return (
<div key={`${firstLayerKey}-item`} className="mb-2">
<FirstLayerDropdown isActive={isActive} isExpanded={isExpanded} innerText={displayText} onClick={() => handleFirstLayerClick(firstLayerKey)} />
{<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">{menuStaticTranslation[lang as keyof typeof menuStaticTranslation].menu}</h3>{renderFirstLayerItems()}</div>;
return (
<>
<div className="flex flex-col">
<div className="mt-1 flex justify-center"><h3 className="text-sm font-semibold mb-1">{menuStaticTranslation[lang as keyof typeof menuStaticTranslation].menu}</h3></div>
<br />
{
availableApplications.length !== 0 && <div className="">{renderFirstLayerItems()}</div>
}
{
availableApplications.length === 0 && <div>
<div className="flex justify-center items-center h-full">
<div className="text-center text-gray-500 dark:text-gray-400">
<p className="text-sm">No menu items available</p>
<p className="text-xs mt-1">Please check your permissions or contact an administrator</p>
</div>
</div>
</div>
}
</div>
</>
)
};
export default MenuItemsSection;

View File

@@ -7,15 +7,26 @@ interface Props {
selectedItem: any;
refreshSelection: () => Promise<void>;
updateSelection: (newSelection: any) => Promise<boolean>;
refreshMenu: () => Promise<void>;
}
const selectFromSelectionList = (item: any, selectedItem: any, updateSelection: (newSelection: any) => Promise<boolean>, refreshSelection: () => Promise<void>) => {
const selectFromSelectionList = async (item: any, selectedItem: any, updateSelection: (newSelection: any) => Promise<boolean>, refreshSelection: () => Promise<void>, refreshMenu: () => Promise<void>) => {
const selectedUUID = selectedItem?.uu_id || selectedItem?.build_living_space_uu_id;
const itemUUID = item?.uu_id || item?.build_living_space_uu_id;
if (selectedUUID !== itemUUID) { updateSelection(item); refreshSelection() }
if (selectedUUID !== itemUUID) {
// First update the selection
await updateSelection(item);
// Then refresh the selection
await refreshSelection();
// Wait a moment to ensure the selection update is processed
setTimeout(async () => {
// Finally refresh the menu
await refreshMenu();
}, 300);
}
}
const RenderOneClientSelection: FC<Props> = ({ item, selectedItem, updateSelection, refreshSelection }) => {
const RenderOneClientSelection: FC<Props> = ({ item, selectedItem, updateSelection, refreshSelection, refreshMenu }) => {
const selectedUUID = selectedItem?.uu_id || selectedItem?.build_living_space_uu_id;
const itemUUID = item?.uu_id || item?.build_living_space_uu_id;
const getDisplayName = () => { if (item.public_name) return item.public_name; if (item.part_name) return item.part_name; return "No Name" };
@@ -24,7 +35,7 @@ const RenderOneClientSelection: FC<Props> = ({ item, selectedItem, updateSelecti
if (selectedUUID !== itemUUID) {
return (
<div key={itemUUID} onClick={() => { selectFromSelectionList(item, selectedItem, updateSelection, refreshSelection) }}
<div key={itemUUID} onClick={() => { selectFromSelectionList(item, selectedItem, updateSelection, refreshSelection, refreshMenu) }}
className="w-full text-xs bg-white shadow rounded-lg overflow-hidden transition-all hover:shadow-md mb-2 cursor-pointer">
<div className="bg-amber-800 p-2 hover:bg-amber-900 transition-all">
<div className="flex items-center">

View File

@@ -12,7 +12,6 @@ interface UserProfileSectionProps {
}
const UserProfileSection: FC<UserProfileSectionProps> = ({ userData, onlineData, selectionData }) => {
console.log("selectionData", selectionData)
if (!selectionData?.activeSelection) return null;
let selectionDefinitionFirst = "";
let selectionDefinitionSecond = "";

View File

@@ -54,6 +54,8 @@ interface UseMenuResult {
export function useMenu(): UseMenuResult {
const { data, availableItems, isLoading, error, refresh, update } =
useContextMenu();
console.log("data", data);
console.log("availableItems", availableItems);
return {
menuData: data,

View File

@@ -17,7 +17,7 @@ const getMenuFromRedis = async (): Promise<ClientMenu> => {
} catch (error) { if (error instanceof AuthError) { throw error } else { throw new AuthError(error instanceof Error ? error.message : "Unknown error") } }
}
const setMenuToRedis = async (menuObject: ClientMenu) => {
const setMenuToRedis = async (menuObject: string[]) => {
try {
const decrpytUserSelection = await functionRetrieveUserSelection()
if (!decrpytUserSelection) throw new AuthError("No user selection found");
@@ -26,7 +26,12 @@ const setMenuToRedis = async (menuObject: ClientMenu) => {
if (!menuObject) throw new AuthError("No menu object provided");
const oldData = await getCompleteFromRedis();
if (!oldData) throw new AuthError("No old data found in redis");
await setCompleteToRedis({ ...oldData, menu: menuObject });
await setCompleteToRedis({
...oldData, menu: {
...oldData.menu,
selectionList: menuObject,
}
});
return true;
} catch (error) { if (error instanceof AuthError) { throw error } else { throw new AuthError(error instanceof Error ? error.message : "Unknown error") } }
}

View File

@@ -16,6 +16,7 @@ import { retrievePageList } from "@/fetchers/mutual/cookies/token";
import { deleteAllCookies } from "@/fetchers/mutual/cookies/cookie-actions";
import { setMenuToRedis } from "@/fetchers/custom/context/page/menu/fetch";
import { LoginViaAccessKeys, LoginSelect } from "@/fetchers/types/login/validations";
import { retrieveValidUrlsOfRestriction } from "../restriction/fetch";
async function logoutActiveSession() {
const response = await fetchDataWithToken(urlLogoutEndpoint, {}, "GET", false);
@@ -157,7 +158,8 @@ async function loginSelectEmployee(payload: LoginSelect) {
if (selectResponse.status === 200 || selectResponse.status === 202) {
try {
console.log("selectResponse", selectResponse) // Get Menu URL's of Employee
const validUrls = await retrieveValidUrlsOfRestriction()
setMenuToRedis(validUrls)
} catch (error) { }
}
return selectResponse;
@@ -169,6 +171,8 @@ async function loginSelectOccupant(payload: LoginSelect) {
if (selectResponse.status === 200 || selectResponse.status === 202) {
try {
console.log("selectResponse", selectResponse) // Get Menu URL's of Occupant
const validUrls = await retrieveValidUrlsOfRestriction()
setMenuToRedis(validUrls)
} catch (error) { }
}
return selectResponse;

View File

@@ -0,0 +1,13 @@
"use server";
import { fetchDataWithToken } from "@/fetchers/fecther";
import { fetchResponseStatus } from "@/fetchers/utils";
import { urlSiteUrls } from "@/fetchers/index";
async function retrieveValidUrlsOfRestriction() {
const response = await fetchDataWithToken(urlSiteUrls, {}, "GET", false);
if (!fetchResponseStatus(response)) throw new Error("No valid urls found");
const data = response.data as any;
return data.sites;
}
export { retrieveValidUrlsOfRestriction }