user selection compoleted tested

This commit is contained in:
2025-06-15 19:05:48 +03:00
parent a48e560ece
commit 9fb517fa15
24 changed files with 574 additions and 313 deletions

View File

@@ -1,36 +1,52 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
# Occupant Types
## Getting Started
Toplantı Başkanı Toplantı Başkanı MT-PRS Toplantı MT
Toplantı Katip Toplantıda tutanak tutan kişi MT-WRT Toplantı MT
Toplantı Katılımcısı Toplantıda sadece katılan kişi MT-ATT Toplantı MT
Toplantı Danışman Toplantıda danışmanlık yapan kişi MT-ADV Toplantı MT
Toplantı Seçilmiş Başkanı Toplantı Seçilmiş Başkanı MT-VPR Toplantı MT
First, run the development server:
Daire Sahibi Daire Sahibi FL-OWN Daire FL
Daire Kiracısı Daire Kiracısı FL-TEN Daire FL
Daire Sakini Daire Sakini FL-RES Daire FL
Daire Sakini Vekili Daire Sakini Vekili FL-REP Daire FL
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Bina Avukatı Bina Avukatı BU-ATT Bina BU
Bina Avukatı Yardımcısı Bina Avukatı Yardımcısı BU-ATA Bina BU
Bina Denetmen Yardımcısı Bina Denetmen Yardımcısı BU-SPA Bina BU
Bina Denetmeni Bina Denetmeni BU-SPV Bina BU
Bina Yönetici Yardımcısı Bina Yönetici Yardımcısı BU-MNA Bina BU
Bina Yöneticisi Bina Yöneticisi BU-MNG Bina BU
Bina Muhasabecisi Bina Muhasabecisi BU-ACC Bina BU
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
Proje Lideri Proje Lideri PRJ-LDR Proje PRJ
Proje Sorumlusu Proje Sorumlusu PRJ-RES Proje PRJ
Proje Ekibi Proje Ekibi PRJ-EMP Proje PRJ
Proje Finans Sorumlusu Proje Finans Sorumlusu PRJ-FIN Proje PRJ
Proje Teknik Sorumlusu Proje Teknik Sorumlusu PRJ-TEC Proje PRJ
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
Bina Teknik Sorumlusu Bina Teknik Sorumlusu BU-TEC Bina BU
Bina Teknik Elemanı Bina Teknik Elemanı BU-EMP Bina BU
Bina Teknik Freelancer Bina Teknik Freelancer BU-FLC Bina BU
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
Daire Mülkiyet Vekili Daire Mülkiyet Vekili FL-DEP Daire FL
## Learn More
# Employee Types
To learn more about Next.js, take a look at the following resources:
General Manager GM0001 General Manager
Business Manager BM0001 Business Manager
IT Manager IT0001 IT Manager
BULK BULK BULK RECORDS OF THE COMPANY
OCCUPANT OCCUPANT OCCUPANT RECORDS OF THE COMPANY
Database Manager DM Database Manager
Network Manager NM Network Manager
Application Manager AM Application Manager
Super User SUE Super User
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
Daire Sakini Vekili Daire Sakini Vekili FL-REP Daire FL
URL Type Tested
/building/accounts/managment/accounts : flat_representative No
## Deploy on Vercel
/definitions/identifications/people : flat_tenant No
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

View File

@@ -1,6 +1,6 @@
import {
getSelectionFromRedis,
setSelectionToRedis,
setActiveSelectionToRedis,
} from "@/fetchers/custom/context/dash/selection/fetch";
import { AuthError } from "@/fetchers/types/context";
import { NextResponse } from "next/server";
@@ -43,7 +43,8 @@ export async function GET() {
export async function POST(request: Request) {
try {
const selection = await request.json();
await setSelectionToRedis(selection);
await setActiveSelectionToRedis(selection);
return NextResponse.json({
status: 200,
data: selection || null,

View File

@@ -1,5 +1,5 @@
import { NextResponse } from "next/server";
import { loginViaAccessKeys } 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,6 +20,7 @@ export async function POST(req: Request): Promise<NextResponse> {
}
const userLogin = await loginViaAccessKeys(dataValidated);
await initFirstSelection(userLogin.data?.firstSelection, userLogin.data?.userType);
if (userLogin.status === 200 || userLogin.status === 202) {
return NextResponse.json({
status: 200,

View File

@@ -0,0 +1,26 @@
import { NextResponse } from "next/server";
import { logoutActiveSession } from "@/fetchers/custom/login/login";
export async function GET(req: Request): Promise<NextResponse> {
try {
const headers = req.headers;
const userLogin = await logoutActiveSession();
if (userLogin.status === 200 || userLogin.status === 202) {
return NextResponse.json({
status: 200,
message: "Logout successfully completed",
data: userLogin.data,
});
} else {
return NextResponse.json({
status: userLogin.status,
message: "Logout NOT successfully completed",
});
}
} catch (error) {
return NextResponse.json({
status: 401,
message: "Logout NOT successfully completed",
});
}
}

View File

@@ -1,9 +1,11 @@
'use client';
import { useRouter } from "next/navigation";
import { FC, useState, useEffect } from "react";
import { HeaderProps } from "@/validations/mutual/dashboard/props";
import { langGetKey } from "@/lib/langGet";
import { LanguageTypes } from "@/validations/mutual/language/validations";
import LanguageSelectionComponent from "@/components/mutual/languageSelection/component";
import { apiGetFetcher } from "@/lib/fetcher";
const translations = {
en: {
@@ -34,30 +36,25 @@ const HeaderComponent: FC<HeaderProps> = ({
userData, userLoading, userError, refreshUser, updateUser
}) => {
const lang = onlineData?.lang as LanguageTypes || 'en';
const router = useRouter();
const [activeTab, setActiveTab] = useState('notifications');
const [isFullscreen, setIsFullscreen] = useState(false);
useEffect(() => {
const handleFullscreenChange = () => {
setIsFullscreen(!!document.fullscreenElement);
};
const handleFullscreenChange = () => { setIsFullscreen(!!document.fullscreenElement) };
document.addEventListener('fullscreenchange', handleFullscreenChange);
return () => {
document.removeEventListener('fullscreenchange', handleFullscreenChange);
};
return () => { document.removeEventListener('fullscreenchange', handleFullscreenChange) };
}, []);
const toggleFullscreen = () => {
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
document.documentElement.requestFullscreen().catch(err => {
console.error(`Error attempting to enable fullscreen: ${err.message}`);
});
if (document.fullscreenElement) { document.exitFullscreen() } else {
document.documentElement.requestFullscreen().catch(err => { console.error(`Error attempting to enable fullscreen: ${err.message}`) });
}
};
const logoutSession = () => { apiGetFetcher({ url: '/api/login/logout', isNoCache: true }).then((logoutSession) => { router.push('/auth/login') }) }
return (
<div className="py-2 px-6 bg-[#f8f4f3] flex items-center shadow-md shadow-black/5 sticky top-0 left-0 z-30">
<button type="button" className="text-lg text-gray-900 font-semibold sidebar-toggle">
@@ -187,10 +184,7 @@ const HeaderComponent: FC<HeaderProps> = ({
<a
role="menuitem"
className="flex items-center text-[13px] py-1.5 px-4 text-gray-600 hover:text-[#f84525] hover:bg-gray-50 cursor-pointer"
onClick={(e) => {
e.preventDefault();
// Handle logout logic here
}}
onClick={logoutSession}
>
{langGetKey(translations[lang], 'logout')}
</a>

View File

@@ -1,39 +1,78 @@
'use client';
import { FC, useState } from "react";
import renderOneClientSelection from "./renderOneClientSelection";
interface ClientSelectionSectionProps {
selectionData: any;
initialSelectedClient?: any;
onClientSelect?: (client: any) => void;
refreshSelection: () => Promise<void>;
updateSelection: (newSelection: any) => Promise<boolean>;
}
const ClientSelectionSection: FC<ClientSelectionSectionProps> = ({
selectionData,
initialSelectedClient = null,
onClientSelect
}) => {
const [selectedClient, setSelectedClient] = useState<any>(initialSelectedClient);
if (!selectionData || !selectionData.selectionList || selectionData.selectionList.length === 0) { return null }
const handleClientSelection = (client: any) => { setSelectedClient(client); if (onClientSelect) { onClientSelect(client) } };
const ClientSelectionSection: FC<ClientSelectionSectionProps> = ({ selectionData, refreshSelection, updateSelection }) => {
const [expandedBuilds, setExpandedBuilds] = useState<{ [key: string]: boolean }>({});
if (!selectionData || !selectionData.selectionList) { return null }
const toggleBuildExpansion = (buildUuid: string) => { setExpandedBuilds(prev => ({ ...prev, [buildUuid]: !prev[buildUuid] })); };
const isArray = Array.isArray(selectionData.selectionList);
return (
<div className="mb-3">
{selectionData.selectionList.map((client: any, index: number) => {
return (
<div
key={client.uu_id || client.id || `client-${index}`}
onClick={() => handleClientSelection(client)}
>
{client && renderOneClientSelection({
item: client,
isSelected: selectedClient?.uu_id === client.uu_id,
onClickHandler: handleClientSelection
})}
</div>
);
})}
{isArray ? (
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 })}
</div>
);
})
) : (
Object.entries(selectionData.selectionList).map(([buildUuid, buildData]: [string, any]) => {
const isExpanded = expandedBuilds[buildUuid] || false;
const selectedBuild = selectionData.selectionList[buildUuid].occupants.filter((client: any) => client.uu_id === selectionData.activeSelection?.uu_id)
const isSelected = selectedBuild.length > 0;
return (
<div key={buildUuid} className="mb-2 border rounded">
{/* Build header - clickable */}
<div
className={`w-full text-xs shadow rounded-lg overflow-hidden mb-2 transition-all cursor-pointer ${isExpanded ? 'border-2 border-blue-500' : ''} hover:shadow-md`}
onClick={() => toggleBuildExpansion(buildUuid)}
>
<div className={`${isExpanded ? 'bg-amber-300' : `${isSelected ? 'bg-blue-400' : 'bg-blue-100'}`} p-2 hover:bg-blue-50 transition-all`}>
<div className="flex items-center">
<div className="w-10 h-10 rounded bg-gray-200 flex items-center justify-center border border-gray-300 mr-2">
<div className="text-gray-500 text-sm font-bold">{buildData.build_name ? buildData.build_name.slice(0, 2).toUpperCase() : 'B'}</div>
</div>
<div className="overflow-hidden">
<h2 className="text-sm font-bold text-gray-800 truncate">{buildData.build_name || buildData.build_no || 'Build'}</h2>
<p className="text-xs text-gray-500 truncate">{buildData.description || `Build #${buildData.build_no || ''}`}</p>
</div>
<div className="ml-auto">
<div className={`${isExpanded ? 'bg-blue-500' : 'bg-gray-300'} rounded-full w-6 h-6 flex items-center justify-center`}>
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d={isExpanded ? "M19 9l-7 7-7-7" : "M9 5l7 7-7 7"} />
</svg>
</div>
</div>
</div>
</div>
</div>
{/* Occupants list - collapsible */}
{isExpanded && (
<div className="pl-3 p-2 border-t">
{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 })}
</div>
))
) : (<div>No occupants found</div>)}
</div>
)}
</div>
);
})
)}
</div>
);
};

View File

@@ -13,26 +13,26 @@ import LoadingContent from "@/components/mutual/loader/component";
const MenuComponent: FC<MenuProps> = ({
activePageUrl, availableApplications, prefix,
onlineData, onlineLoading, onlineError,
userData, userLoading, userError,
selectionData, selectionLoading, selectionError,
menuData, menuLoading, menuError
onlineData, onlineLoading, onlineError, refreshOnline, updateOnline,
userData, userLoading, userError, refreshUser, updateUser,
selectionData, selectionLoading, selectionError, refreshSelection, updateSelection,
menuData, menuLoading, menuError, refreshMenu, updateMenu
}) => {
if (menuLoading) { return <MenuLoadingState /> }
if (menuError) { return <MenuErrorState error={menuError} />; }
if (availableApplications.length === 0) { return <MenuEmptyState />; }
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-content"} plane="h-full w-full" /></div>}>
<UserProfileSection userData={userData} onlineData={onlineData} />
<UserProfileSection userData={userData} onlineData={onlineData} selectionData={selectionData} />
</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} initialSelectedClient={selectionData} onClientSelect={handleClientSelection} />
<ClientSelectionSection selectionData={selectionData} refreshSelection={refreshSelection} updateSelection={updateSelection} />
</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

@@ -2,32 +2,44 @@
import { FC } from "react";
import { Briefcase } from "lucide-react";
interface Props {
item: any;
isSelected: boolean;
onClickHandler: (item: any) => void;
selectedItem: any;
refreshSelection: () => Promise<void>;
updateSelection: (newSelection: any) => Promise<boolean>;
}
const RenderOneClientSelection: FC<Props> = ({ item, isSelected, onClickHandler }) => {
if (isSelected) {
const selectFromSelectionList = (item: any, selectedItem: any, updateSelection: (newSelection: any) => Promise<boolean>, refreshSelection: () => 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() }
}
const RenderOneClientSelection: FC<Props> = ({ item, selectedItem, updateSelection, refreshSelection }) => {
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" };
const getDescription = () => { if (item.duty) return item.duty; if (item.description) return item.description; if (item.code) return item.code; return "" };
const getInitials = () => { const name = getDisplayName(); return name.slice(0, 2) };
if (selectedUUID !== itemUUID) {
return (
<div key={item.uu_id} onClick={() => { onClickHandler(item) }}
<div key={itemUUID} onClick={() => { selectFromSelectionList(item, selectedItem, updateSelection, refreshSelection) }}
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-300 p-2 hover:bg-amber-400 transition-all">
<div className="bg-amber-800 p-2 hover:bg-amber-900 transition-all">
<div className="flex items-center">
<div className="mr-2 relative">
<div className="w-8 h-8 rounded-full bg-amber-400 flex items-center justify-center overflow-hidden border border-white">
{item.avatar ? (<img src={item.avatar} alt="Company" className="w-full h-full object-cover" />) :
(<div className="text-white text-xs font-bold">{(item.public_name || "No Name").slice(0, 2)}</div>)}
<div className="w-8 h-8 rounded-full bg-amber-700 flex items-center justify-center overflow-hidden border border-white">
{item.avatar ? (<img src={item.avatar} alt="Occupant" className="w-full h-full object-cover" />) :
(<div className="text-white text-xs font-bold">{getInitials()}</div>)}
</div>
<div className="absolute -bottom-0.5 -right-0.5 bg-white p-0.5 rounded-full border border-amber-400">
<Briefcase size={8} className="text-amber-600" />
<div className="absolute -bottom-0.5 -right-0.5 bg-white p-0.5 rounded-full border border-amber-600">
<Briefcase size={8} className="text-amber-800" />
</div>
</div>
<div className="overflow-hidden">
<h2 className="text-xs font-bold text-black truncate">{item.public_name} {item.company_type}</h2>
<p className="text-xs text-amber-800 truncate">{item.duty}</p>
<h2 className="text-xs font-bold text-white truncate">{getDisplayName()} {item.company_type || ''}</h2>
<p className="text-xs text-amber-200 truncate">{getDescription()}</p>
</div>
</div>
</div>
@@ -35,21 +47,21 @@ const RenderOneClientSelection: FC<Props> = ({ item, isSelected, onClickHandler
)
}
return (
<div key={item.uu_id} className="w-full text-xs bg-white shadow rounded-lg overflow-hidden transition-all mb-2 cursor-pointer">
<div className="bg-gray-100 p-2">
<div key={itemUUID} className="w-full text-xs bg-white shadow rounded-lg overflow-hidden transition-all mb-2 pointer-events-none opacity-70">
<div className="bg-amber-300 p-2">
<div className="flex items-center">
<div className="mr-2 relative">
<div className="w-8 h-8 rounded-full bg-gray-300 flex items-center justify-center overflow-hidden border border-white">
{item.avatar ? (<img src={item.avatar} alt="Company" className="w-full h-full object-cover" />) :
(<div className="text-white text-xs font-bold">{(item.duty || "No Duty").slice(0, 2)}</div>)}
<div className="w-8 h-8 rounded-full bg-gray-400 flex items-center justify-center overflow-hidden border border-white">
{item.avatar ? (<img src={item.avatar} alt="Occupant" className="w-full h-full object-cover opacity-70" />) :
(<div className="text-white text-xs font-bold">{getInitials()}</div>)}
</div>
<div className="absolute -bottom-0.5 -right-0.5 bg-white p-0.5 rounded-full border border-gray-300">
<Briefcase size={8} className="text-gray-600" />
<div className="absolute -bottom-0.5 -right-0.5 bg-white p-0.5 rounded-full border border-gray-400">
<Briefcase size={8} className="text-gray-500" />
</div>
</div>
<div className="overflow-hidden">
<h2 className="text-xs font-bold text-gray-700 truncate">{item.public_name} {item.company_type}</h2>
<p className="text-xs text-gray-600 truncate">{item.duty}</p>
<h2 className="text-xs font-bold text-gray-600 truncate">{getDisplayName()} {item.company_type || ''}</h2>
<p className="text-xs text-gray-500 truncate">{getDescription()}</p>
</div>
</div>
</div>

View File

@@ -1,15 +1,29 @@
'use client';
import { FC } from "react";
import { ClientUser } from "@/types/mutual/context/validations";
import { ClientOnline } from "@/types/mutual/context/validations";
import { ClientUser } from "@/types/mutual/context";
import { ClientOnline } from "@/types/mutual/context";
import { ClientSelection } from "@/types/mutual/context";
interface UserProfileSectionProps {
userData: ClientUser | null;
onlineData: ClientOnline | null;
selectionData: ClientSelection;
}
const UserProfileSection: FC<UserProfileSectionProps> = ({ userData, onlineData }) => {
const UserProfileSection: FC<UserProfileSectionProps> = ({ userData, onlineData, selectionData }) => {
console.log("selectionData", selectionData)
if (!selectionData?.activeSelection) return null;
let selectionDefinitionFirst = "";
let selectionDefinitionSecond = "";
if (selectionData.activeSelection?.description && selectionData.activeSelection?.part_name) {
selectionDefinitionFirst = selectionData?.activeSelection?.description || "No selection";
selectionDefinitionSecond = selectionData?.activeSelection?.part_name || "No selection";
} else {
selectionDefinitionFirst = selectionData?.activeSelection?.public_name || "No selection";
selectionDefinitionSecond = selectionData?.activeSelection?.duty || "No selection";
}
if (!userData) return null;
return (
<div className="mb-2">
@@ -26,7 +40,8 @@ const UserProfileSection: FC<UserProfileSectionProps> = ({ userData, onlineData
<div className="overflow-hidden">
<h2 className="text-sm font-bold text-black truncate">{userData?.person ? `${userData.person.firstname} ${userData.person.surname}` : 'User'}</h2>
<p className="text-xs text-amber-800 truncate">{userData?.email || 'No email'}</p>
<p className="text-xs font-medium capitalize">{onlineData?.userType || 'guest'}</p>
<p className="text-xs font-medium capitalize">{selectionDefinitionFirst}</p>
<p className="text-xs font-medium capitalize">{selectionDefinitionSecond || ''}</p>
</div>
</div>
</div>

View File

@@ -3,6 +3,7 @@ import { redis } from "@/lib/redis";
import { functionRetrieveUserSelection } from "@/fetchers/fecther";
import { ClientSelection, AuthError } from "@/fetchers/types/context";
import { getCompleteFromRedis, setCompleteToRedis } from "@/fetchers/custom/context/complete/fetch";
import { loginSelectEmployee, loginSelectOccupant } from "@/fetchers/custom/login/login";
const getSelectionFromRedis = async (): Promise<ClientSelection> => {
try {
@@ -17,7 +18,7 @@ const getSelectionFromRedis = async (): Promise<ClientSelection> => {
} catch (error) { return { selectionList: [], activeSelection: {} } }
}
const setSelectionToRedis = async (selectionObject: ClientSelection) => {
const setActiveSelectionToRedis = async (selectionObject: any) => {
try {
const decrpytUserSelection = await functionRetrieveUserSelection()
if (!decrpytUserSelection) throw new AuthError("No user selection found");
@@ -30,10 +31,19 @@ const setSelectionToRedis = async (selectionObject: ClientSelection) => {
const oldData = await getCompleteFromRedis();
if (!oldData) throw new AuthError("No old data found in redis");
await setCompleteToRedis({ ...oldData, selection: selectionObject })
await setCompleteToRedis({
...oldData, selection: {
selectionList: oldData.selection.selectionList,
activeSelection: selectionObject
}
})
if (oldData.online.userType.toUpperCase() === "EMPLOYEE") {
await loginSelectEmployee({ uuid: selectionObject.uuid });
} else if (oldData.online.userType.toUpperCase() === "OCCUPANT") {
await loginSelectOccupant({ uuid: selectionObject.build_living_space_uu_id });
}
return true;
} catch (error) {
// Re-throw AuthError instances, wrap other errors as AuthError
if (error instanceof AuthError) {
throw error;
} else {
@@ -42,4 +52,4 @@ const setSelectionToRedis = async (selectionObject: ClientSelection) => {
}
}
export { getSelectionFromRedis, setSelectionToRedis };
export { getSelectionFromRedis, setActiveSelectionToRedis };

View File

@@ -15,7 +15,7 @@ import {
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, LoginSelectOccupant } from "@/fetchers/types/login/validations";
import { LoginViaAccessKeys, LoginSelect } from "@/fetchers/types/login/validations";
async function logoutActiveSession() {
const response = await fetchDataWithToken(urlLogoutEndpoint, {}, "GET", false);
@@ -25,29 +25,50 @@ async function logoutActiveSession() {
async function initRedis(loginRespone: any, firstSelection: any, accessToken: string, redisKey: string) {
let alreadyAtRedis = null
try {
const redisData = await getCompleteFromRedis();
alreadyAtRedis = redisData;
} catch (error) { }
console.log("loginRespone", loginRespone)
console.log("firstSelection", firstSelection)
console.log("accessToken", accessToken)
console.log("redisKey", redisKey)
if (!alreadyAtRedis) {
const loginObjectToRedis = {
online: {
...defaultValuesOnline,
lastLogin: new Date(),
userType: `${loginRespone.user_type}`.toUpperCase(),
lang: loginRespone.user.person.country_code.toLowerCase(),
},
pageConfig: defaultValuesPageConfig,
menu: defaultValuesMenu,
header: defaultValuesHeader,
selection: { selectionList: loginRespone.selection_list, activeSelection: firstSelection },
user: loginRespone.user,
settings: { lastOnline: new Date(), token: accessToken },
chatRoom: [],
notifications: [],
messages: [],
if (loginRespone.user_type.toUpperCase() === "EMPLOYEE") {
const loginObjectToRedis = {
online: { ...defaultValuesOnline, lastLogin: new Date(), userType: `${loginRespone.user_type}`.toUpperCase(), lang: loginRespone.user.person.country_code.toLowerCase() },
pageConfig: defaultValuesPageConfig,
menu: defaultValuesMenu,
header: defaultValuesHeader,
selection: { selectionList: loginRespone.selection_list, activeSelection: firstSelection },
user: loginRespone.user,
settings: { lastOnline: new Date(), token: accessToken },
chatRoom: [],
notifications: [],
messages: [],
}
await setNewCompleteToRedis(loginObjectToRedis, redisKey);
} else if (loginRespone.user_type.toUpperCase() === "OCCUPANT") {
const loginObjectToRedis = {
online: { ...defaultValuesOnline, lastLogin: new Date(), userType: `${loginRespone.user_type}`.toUpperCase(), lang: "tr" },
pageConfig: defaultValuesPageConfig,
menu: defaultValuesMenu,
header: defaultValuesHeader,
selection: { selectionList: loginRespone.selection_list, activeSelection: firstSelection },
user: loginRespone.user,
settings: { lastOnline: new Date(), token: accessToken },
chatRoom: [],
notifications: [],
messages: [],
}
await setNewCompleteToRedis(loginObjectToRedis, redisKey);
}
await setNewCompleteToRedis(loginObjectToRedis, redisKey);
}
}
async function initFirstSelection(firstSelection: any, userType: string) {
if (userType === "EMPLOYEE") {
const uuid = firstSelection.uuid;
await loginSelectEmployee({ uuid });
} else if (userType === "OCCUPANT") {
const uuid = firstSelection.build_living_space_uu_id;
await loginSelectOccupant({ uuid });
}
}
@@ -68,22 +89,24 @@ async function loginViaAccessKeys(payload: LoginViaAccessKeys) {
if (response.status === 200 || response.status === 202) {
const loginRespone: any = response?.data;
const firstSelection = loginRespone.selection_list.find((item: any) => item.uu_id === loginRespone.selection_list[0].uu_id);
let firstSelection = null
if (loginRespone.user_type.toUpperCase() === "EMPLOYEE") {
firstSelection = loginRespone.selection_list.find((item: any) => item.uu_id === loginRespone.selection_list[0].uu_id);
} else if (loginRespone.user_type.toUpperCase() === "OCCUPANT") {
const firstKeyOfSelectionList = Object.keys(loginRespone.selection_list)[0];
firstSelection = loginRespone.selection_list[firstKeyOfSelectionList].occupants[0];
}
const nextCrypto = new NextCrypto(tokenSecret);
const accessToken = await nextCrypto.encrypt(loginRespone.access_token);
const redisKey = `CLIENT:${loginRespone.user_type.toUpperCase()}:${firstSelection.uu_id}`;
const userType = loginRespone.user_type.toUpperCase()
const redisKey = `CLIENT:${userType}:${loginRespone.user.uuid}`;
const redisKeyAccess = await nextCrypto.encrypt(redisKey);
const usersSelection = await nextCrypto.encrypt(
JSON.stringify({
selected: firstSelection.uu_id,
userType: loginRespone.user_type.toUpperCase(),
redisKey,
})
);
const usersSelection = await nextCrypto.encrypt(JSON.stringify({ selected: firstSelection, userType, redisKey }));
await initRedis(loginRespone, firstSelection, accessToken, redisKey);
cookieStore.set({
name: "eys-zzz",
value: accessToken,
@@ -99,12 +122,16 @@ async function loginViaAccessKeys(payload: LoginViaAccessKeys) {
value: usersSelection,
...cookieObject,
});
try {
return {
completed: true,
message: "Login successful",
status: 200,
data: loginRespone,
data: {
userType,
firstSelection,
},
};
} catch (error) {
console.error("JSON parse error:", error);
@@ -112,7 +139,10 @@ async function loginViaAccessKeys(payload: LoginViaAccessKeys) {
completed: false,
message: "Login NOT successful",
status: 401,
data: "{}",
data: {
userType,
firstSelection,
},
};
}
}
@@ -135,65 +165,32 @@ async function loginViaAccessKeys(payload: LoginViaAccessKeys) {
}
async function loginSelectEmployee(payload: LoginSelect) {
const cookieStore = await cookies();
const nextCrypto = new NextCrypto(tokenSecret);
const employeeUUID = payload.uuid;
const redisKey = `CLIENT:EMPLOYEE:${employeeUUID}`;
const selectResponse: any = await fetchDataWithToken(urlLoginSelectEndpoint, { uuid: employeeUUID }, "POST", false);
cookieStore.delete({ name: "eys-sel", ...cookieObject });
console.log("selectResponse", selectResponse)
if (selectResponse.status === 200 || selectResponse.status === 202) {
const usersSelection = await nextCrypto.encrypt(
JSON.stringify({
selected: employeeUUID,
userType: "employee",
redisKey,
})
);
cookieStore.set({
name: "eys-sel",
value: usersSelection,
...cookieObject,
});
try {
const pageList = await retrievePageList()
await setMenuToRedis({
selectionList: pageList,
activeSelection: "/dashboard"
})
console.log("selectResponse", selectResponse)
} catch (error) { }
}
return selectResponse;
}
async function loginSelectOccupant(payload: LoginSelectOccupant) {
async function loginSelectOccupant(payload: LoginSelect) {
const livingSpaceUUID = payload.uuid;
const cookieStore = await cookies();
const nextCrypto = new NextCrypto(tokenSecret);
const selectResponse: any = await fetchDataWithToken(urlLoginSelectEndpoint, { uuid: livingSpaceUUID }, "POST", false);
const redisKey = `CLIENT:OCCUPANT:${livingSpaceUUID}`;
cookieStore.delete("eys-sel");
console.log("selectResponse", selectResponse)
if (selectResponse.status === 200 || selectResponse.status === 202) {
const usersSelection = await nextCrypto.encrypt(
JSON.stringify({
selected: livingSpaceUUID,
userType: "OCCUPANT",
redisKey,
})
);
cookieStore.set({
name: "eys-sel",
value: usersSelection,
...cookieObject,
});
try {
console.log("selectResponse", selectResponse)
} catch (error) { }
}
return selectResponse;
}
export {
loginViaAccessKeys,
initFirstSelection,
loginSelectEmployee,
loginSelectOccupant,
logoutActiveSession,

View File

@@ -8,8 +8,4 @@ interface LoginSelect {
uuid: string;
}
interface LoginSelectOccupant {
uuid: any;
}
export type { LoginViaAccessKeys, LoginSelect, LoginSelectOccupant };
export type { LoginViaAccessKeys, LoginSelect };

View File

@@ -1,10 +1,7 @@
import { DashboardPage } from "@/components/custom/content/DashboardPage";
const pageIndexMulti: Record<string, Record<string, React.FC<any>>> = {
"/dashboard": {
DashboardPage: DashboardPage,
},
// Add more pages as needed
"/dashboard": { DashboardPage: DashboardPage },
};
export { pageIndexMulti };