tested client-fronted login session

This commit is contained in:
Berkay 2025-05-21 18:53:58 +03:00
parent 82d16ed3c9
commit 6ce95b5df6
33 changed files with 570 additions and 980 deletions

View File

@ -44,10 +44,7 @@ async function coreFetch<T>(
const { method = "POST", cache = false, timeout = DEFAULT_TIMEOUT } = options; const { method = "POST", cache = false, timeout = DEFAULT_TIMEOUT } = options;
try { try {
// Setup controller for timeout handling
const controller = new AbortController(); const controller = new AbortController();
// Prepare fetch options
const fetchOptions: RequestInit = { const fetchOptions: RequestInit = {
method, method,
headers, headers,
@ -55,26 +52,17 @@ async function coreFetch<T>(
signal: controller.signal, signal: controller.signal,
}; };
// Add body for non-GET requests with payload
if (method !== "GET" && payload) { if (method !== "GET" && payload) {
fetchOptions.body = JSON.stringify( fetchOptions.body = JSON.stringify(
payload.payload ? payload.payload : payload payload.payload ? payload.payload : payload
); );
} }
// Create timeout promise
const timeoutPromise = createTimeoutPromise(timeout, controller); const timeoutPromise = createTimeoutPromise(timeout, controller);
// Execute request with timeout
const response = await Promise.race([ const response = await Promise.race([
fetch(url, fetchOptions), fetch(url, fetchOptions),
timeoutPromise, timeoutPromise,
]); ]);
// Parse response
const responseData = await response.json(); const responseData = await response.json();
// Return standardized response
return { return {
status: response.status, status: response.status,
data: responseData || ({} as T), data: responseData || ({} as T),
@ -116,12 +104,8 @@ async function fetchDataWithToken<T>(
cache: boolean = false, cache: boolean = false,
timeout: number = DEFAULT_TIMEOUT timeout: number = DEFAULT_TIMEOUT
): Promise<ApiResponse<T>> { ): Promise<ApiResponse<T>> {
const accessToken = (await retrieveAccessToken()); const accessToken = await retrieveAccessToken();
const headers = { const headers = { ...defaultHeaders, "eys-acs-tkn": accessToken };
...defaultHeaders,
"eys-acs-tkn": accessToken,
};
return coreFetch<T>(endpoint, { method, cache, timeout }, headers, payload); return coreFetch<T>(endpoint, { method, cache, timeout }, headers, payload);
} }
@ -136,12 +120,8 @@ async function updateDataWithToken<T>(
cache: boolean = false, cache: boolean = false,
timeout: number = DEFAULT_TIMEOUT timeout: number = DEFAULT_TIMEOUT
): Promise<ApiResponse<T>> { ): Promise<ApiResponse<T>> {
const accessToken = (await retrieveAccessToken()) || ""; const accessToken = await retrieveAccessToken();
const headers = { const headers = { ...defaultHeaders, "eys-acs-tkn": accessToken };
...defaultHeaders,
"eys-acs-tkn": accessToken,
};
return coreFetch<T>( return coreFetch<T>(
`${endpoint}/${uuid}`, `${endpoint}/${uuid}`,
{ method, cache, timeout }, { method, cache, timeout },

View File

@ -2,6 +2,7 @@
import { redis } from "@/lib/redis"; import { redis } from "@/lib/redis";
import { functionRetrieveUserSelection } from "@/apifetchers/utils"; import { functionRetrieveUserSelection } from "@/apifetchers/utils";
import { ClientRedisToken } from "@/types/mutual/context/validations"; import { ClientRedisToken } from "@/types/mutual/context/validations";
import { AuthError } from "@/types/mutual/context/validations";
// Redis operation timeout (5 seconds) // Redis operation timeout (5 seconds)
const REDIS_TIMEOUT = 5000; const REDIS_TIMEOUT = 5000;
@ -76,51 +77,20 @@ const defaultValues: ClientRedisToken = {
const getCompleteFromRedis = async (): Promise<ClientRedisToken> => { const getCompleteFromRedis = async (): Promise<ClientRedisToken> => {
try { try {
let decrpytUserSelection; let decrpytUserSelection;
try { try { decrpytUserSelection = await functionRetrieveUserSelection() } catch (error) { return defaultValues }
decrpytUserSelection = await functionRetrieveUserSelection();
} catch (error) {
console.error('Error retrieving user selection:', error);
return defaultValues;
}
const redisKey = decrpytUserSelection?.redisKey; const redisKey = decrpytUserSelection?.redisKey;
if (!redisKey) { return defaultValues }
if (!redisKey) { if (redisKey === "default") { return defaultValues }
console.error("No redis key found in user selection");
return defaultValues;
}
if (redisKey === "default") {
return defaultValues;
}
try { try {
const timeoutPromise = new Promise<string | null>((_, reject) => { const timeoutPromise = new Promise<string | null>((_, reject) => {
setTimeout(() => reject(new Error('Redis operation timed out')), REDIS_TIMEOUT); setTimeout(() => reject(new Error('Redis operation timed out')), REDIS_TIMEOUT);
}); });
const result = await Promise.race([redis.get(`${redisKey}`), timeoutPromise]);
// Race the Redis operation against the timeout if (!result) { return defaultValues }
const result = await Promise.race([ try { const parsedResult = JSON.parse(result); return parsedResult } catch (parseError) { return defaultValues }
redis.get(`${redisKey}`), } catch (redisError) { return defaultValues }
timeoutPromise } catch (error) { return defaultValues }
]);
if (!result) {
return defaultValues;
}
try {
const parsedResult = JSON.parse(result);
return parsedResult;
} catch (parseError) {
return defaultValues;
}
} catch (redisError) {
return defaultValues;
}
} catch (error) {
return defaultValues;
}
} }
/** /**
@ -130,41 +100,18 @@ const getCompleteFromRedis = async (): Promise<ClientRedisToken> => {
*/ */
const setCompleteToRedis = async (completeObject: ClientRedisToken): Promise<boolean> => { const setCompleteToRedis = async (completeObject: ClientRedisToken): Promise<boolean> => {
try { try {
if (!completeObject) { if (!completeObject) { return false }
return false;
}
let decrpytUserSelection; let decrpytUserSelection;
try { try { decrpytUserSelection = await functionRetrieveUserSelection() } catch (error) { return false }
decrpytUserSelection = await functionRetrieveUserSelection(); if (!decrpytUserSelection) { return false }
} catch (error) {
return false;
}
if (!decrpytUserSelection) {
return false;
}
const redisKey = decrpytUserSelection?.redisKey; const redisKey = decrpytUserSelection?.redisKey;
if (!redisKey) { if (!redisKey) { return false }
return false;
}
try { try {
const timeoutPromise = new Promise((_, reject) => { const timeoutPromise = new Promise((_, reject) => { setTimeout(() => reject(new Error('Redis operation timed out')), REDIS_TIMEOUT) });
setTimeout(() => reject(new Error('Redis operation timed out')), REDIS_TIMEOUT); await Promise.race([redis.set(redisKey, JSON.stringify(completeObject)), timeoutPromise]);
});
await Promise.race([
redis.set(redisKey, JSON.stringify(completeObject)),
timeoutPromise
]);
return true; return true;
} catch (redisError) { } catch (redisError) { return false }
return false; } catch (error) { return false }
}
} catch (error) {
return false;
}
} }
/** /**
@ -175,29 +122,14 @@ const setCompleteToRedis = async (completeObject: ClientRedisToken): Promise<boo
*/ */
const setNewCompleteToRedis = async (completeObject: ClientRedisToken, redisKey: string): Promise<boolean> => { const setNewCompleteToRedis = async (completeObject: ClientRedisToken, redisKey: string): Promise<boolean> => {
try { try {
if (!redisKey) { if (!redisKey) { return false }
return false; if (!completeObject) { return false }
}
if (!completeObject) {
return false;
}
try { try {
const timeoutPromise = new Promise((_, reject) => { const timeoutPromise = new Promise((_, reject) => { setTimeout(() => reject(new Error('Redis operation timed out')), REDIS_TIMEOUT) });
setTimeout(() => reject(new Error('Redis operation timed out')), REDIS_TIMEOUT); await Promise.race([redis.set(redisKey, JSON.stringify(completeObject)), timeoutPromise])
});
await Promise.race([
redis.set(redisKey, JSON.stringify(completeObject)),
timeoutPromise
]);
return true; return true;
} catch (redisError) { } catch (redisError) { return false }
return false; } catch (error) { return false }
}
} catch (error) {
return false;
}
} }
export { getCompleteFromRedis, setCompleteToRedis, setNewCompleteToRedis }; export { getCompleteFromRedis, setCompleteToRedis, setNewCompleteToRedis };

View File

@ -3,6 +3,7 @@ import { redis } from "@/lib/redis";
import { functionRetrieveUserSelection } from "@/apifetchers/utils"; import { functionRetrieveUserSelection } from "@/apifetchers/utils";
import { ClientSelection } from "@/types/mutual/context/validations"; import { ClientSelection } from "@/types/mutual/context/validations";
import { getCompleteFromRedis, setCompleteToRedis } from "@/apifetchers/mutual/context/complete/fetch"; import { getCompleteFromRedis, setCompleteToRedis } from "@/apifetchers/mutual/context/complete/fetch";
import { AuthError } from "@/types/mutual/context/validations";
const getSelectionFromRedis = async (): Promise<ClientSelection> => { const getSelectionFromRedis = async (): Promise<ClientSelection> => {
try { try {
@ -18,15 +19,28 @@ const getSelectionFromRedis = async (): Promise<ClientSelection> => {
} }
const setSelectionToRedis = async (selectionObject: ClientSelection) => { const setSelectionToRedis = async (selectionObject: ClientSelection) => {
try {
const decrpytUserSelection = await functionRetrieveUserSelection() const decrpytUserSelection = await functionRetrieveUserSelection()
if (!decrpytUserSelection) throw new Error("No user selection found"); if (!decrpytUserSelection) throw new AuthError("No user selection found");
const redisKey = decrpytUserSelection?.redisKey; const redisKey = decrpytUserSelection?.redisKey;
if (!redisKey) throw new Error("No redis key found"); if (!redisKey) throw new AuthError("No redis key found");
if (!selectionObject) throw new Error("No selection object provided");
if (!selectionObject) throw new AuthError("No selection object provided");
const oldData = await getCompleteFromRedis(); const oldData = await getCompleteFromRedis();
if (!oldData) throw new Error("No old data found in redis"); if (!oldData) throw new AuthError("No old data found in redis");
await setCompleteToRedis({ ...oldData, selection: selectionObject }) await setCompleteToRedis({ ...oldData, selection: selectionObject })
return true; return true;
} catch (error) {
// Re-throw AuthError instances, wrap other errors as AuthError
if (error instanceof AuthError) {
throw error;
} else {
throw new AuthError(error instanceof Error ? error.message : "Unknown error");
}
}
} }
export { getSelectionFromRedis, setSelectionToRedis }; export { getSelectionFromRedis, setSelectionToRedis };

View File

@ -3,28 +3,46 @@ import { redis } from "@/lib/redis";
import { functionRetrieveUserSelection } from "@/apifetchers/utils"; import { functionRetrieveUserSelection } from "@/apifetchers/utils";
import { ClientSettings } from "@/types/mutual/context/validations"; import { ClientSettings } from "@/types/mutual/context/validations";
import { getCompleteFromRedis, setCompleteToRedis } from "@/apifetchers/mutual/context/complete/fetch"; import { getCompleteFromRedis, setCompleteToRedis } from "@/apifetchers/mutual/context/complete/fetch";
import { AuthError } from "@/types/mutual/context/validations";
const getSettingsFromRedis = async (): Promise<ClientSettings> => { const getSettingsFromRedis = async (): Promise<ClientSettings> => {
try {
const decrpytUserSelection = await functionRetrieveUserSelection() const decrpytUserSelection = await functionRetrieveUserSelection()
const redisKey = decrpytUserSelection?.redisKey; const redisKey = decrpytUserSelection?.redisKey;
if (!redisKey) throw new Error("No redis key found"); if (!redisKey) throw new AuthError("No redis key found");
const result = await redis.get(`${redisKey}`); const result = await redis.get(`${redisKey}`);
if (!result) throw new Error("No data found in redis"); if (!result) throw new AuthError("No data found in redis");
const parsedResult = JSON.parse(result); const parsedResult = JSON.parse(result);
if (!parsedResult.settings) throw new Error("No settings found in redis"); if (!parsedResult.settings) throw new AuthError("No settings found in redis");
return parsedResult.settings; return parsedResult.settings;
} catch (error) {
if (error instanceof AuthError) { throw error }
throw new AuthError(error instanceof Error ? error.message : "Unknown error");
}
} }
const setSettingsToRedis = async (settingsObject: ClientSettings) => { const setSettingsToRedis = async (settingsObject: ClientSettings) => {
try {
const decrpytUserSelection = await functionRetrieveUserSelection() const decrpytUserSelection = await functionRetrieveUserSelection()
if (!decrpytUserSelection) throw new Error("No user selection found"); if (!decrpytUserSelection) throw new AuthError("No user selection found");
const redisKey = decrpytUserSelection?.redisKey; const redisKey = decrpytUserSelection?.redisKey;
if (!redisKey) throw new Error("No redis key found"); if (!redisKey) throw new AuthError("No redis key found");
if (!settingsObject) throw new Error("No settings object provided");
if (!settingsObject) throw new AuthError("No settings object provided");
const oldData = await getCompleteFromRedis(); const oldData = await getCompleteFromRedis();
if (!oldData) throw new Error("No old data found in redis"); if (!oldData) throw new AuthError("No old data found in redis");
await setCompleteToRedis({ ...oldData, settings: settingsObject }) await setCompleteToRedis({ ...oldData, settings: settingsObject })
return true; return true;
} catch (error) {
if (error instanceof AuthError) { throw error }
throw new AuthError(error instanceof Error ? error.message : "Unknown error");
}
} }
export { getSettingsFromRedis, setSettingsToRedis }; export { getSettingsFromRedis, setSettingsToRedis };

View File

@ -3,28 +3,46 @@ import { redis } from "@/lib/redis";
import { functionRetrieveUserSelection } from "@/apifetchers/utils"; import { functionRetrieveUserSelection } from "@/apifetchers/utils";
import { ClientUser } from "@/types/mutual/context/validations"; import { ClientUser } from "@/types/mutual/context/validations";
import { getCompleteFromRedis, setCompleteToRedis } from "@/apifetchers/mutual/context/complete/fetch"; import { getCompleteFromRedis, setCompleteToRedis } from "@/apifetchers/mutual/context/complete/fetch";
import { AuthError } from "@/types/mutual/context/validations";
const getUserFromRedis = async (): Promise<ClientUser> => { const getUserFromRedis = async (): Promise<ClientUser> => {
try {
const decrpytUserSelection = await functionRetrieveUserSelection() const decrpytUserSelection = await functionRetrieveUserSelection()
const redisKey = decrpytUserSelection?.redisKey; const redisKey = decrpytUserSelection?.redisKey;
if (!redisKey) throw new Error("No redis key found"); if (!redisKey) throw new AuthError("No redis key found");
const result = await redis.get(`${redisKey}`); const result = await redis.get(`${redisKey}`);
if (!result) throw new Error("No data found in redis"); if (!result) throw new AuthError("No data found in redis");
const parsedResult = JSON.parse(result); const parsedResult = JSON.parse(result);
if (!parsedResult.user) throw new Error("No user found in redis"); if (!parsedResult.user) throw new AuthError("No user found in redis");
return parsedResult.user; return parsedResult.user;
} catch (error) {
if (error instanceof AuthError) { throw error }
throw new AuthError(error instanceof Error ? error.message : "Unknown error");
}
} }
const setUserToRedis = async (userObject: ClientUser) => { const setUserToRedis = async (userObject: ClientUser) => {
try {
const decrpytUserSelection = await functionRetrieveUserSelection() const decrpytUserSelection = await functionRetrieveUserSelection()
if (!decrpytUserSelection) throw new Error("No user selection found"); if (!decrpytUserSelection) throw new AuthError("No user selection found");
const redisKey = decrpytUserSelection?.redisKey; const redisKey = decrpytUserSelection?.redisKey;
if (!redisKey) throw new Error("No redis key found"); if (!redisKey) throw new AuthError("No redis key found");
if (!userObject) throw new Error("No user object provided");
if (!userObject) throw new AuthError("No user object provided");
const oldData = await getCompleteFromRedis(); const oldData = await getCompleteFromRedis();
if (!oldData) throw new Error("No old data found in redis"); if (!oldData) throw new AuthError("No old data found in redis");
await setCompleteToRedis({ ...oldData, user: userObject }); await setCompleteToRedis({ ...oldData, user: userObject });
return true; return true;
} catch (error) {
if (error instanceof AuthError) { throw error }
throw new AuthError(error instanceof Error ? error.message : "Unknown error");
}
} }
export { getUserFromRedis, setUserToRedis }; export { getUserFromRedis, setUserToRedis };

View File

@ -3,28 +3,39 @@ import { redis } from "@/lib/redis";
import { functionRetrieveUserSelection } from "@/apifetchers/utils"; import { functionRetrieveUserSelection } from "@/apifetchers/utils";
import { ClientSettings } from "@/types/mutual/context/validations"; import { ClientSettings } from "@/types/mutual/context/validations";
import { getCompleteFromRedis, setCompleteToRedis } from "@/apifetchers/mutual/context/complete/fetch"; import { getCompleteFromRedis, setCompleteToRedis } from "@/apifetchers/mutual/context/complete/fetch";
import { AuthError } from "@/types/mutual/context/validations";
const getConfigFromRedis = async (): Promise<ClientSettings> => { const getConfigFromRedis = async (): Promise<ClientSettings> => {
try {
const decrpytUserSelection = await functionRetrieveUserSelection() const decrpytUserSelection = await functionRetrieveUserSelection()
const redisKey = decrpytUserSelection?.redisKey; const redisKey = decrpytUserSelection?.redisKey;
if (!redisKey) throw new Error("No redis key found"); if (!redisKey) throw new AuthError("No redis key found");
const result = await redis.get(`${redisKey}`); const result = await redis.get(`${redisKey}`);
if (!result) throw new Error("No data found in redis"); if (!result) throw new AuthError("No data found in redis");
const parsedResult = JSON.parse(result); const parsedResult = JSON.parse(result);
if (!parsedResult.settings) throw new Error("No settings found in redis"); if (!parsedResult.settings) throw new AuthError("No settings found in redis");
return parsedResult.settings; return parsedResult.settings;
} catch (error) {
if (error instanceof AuthError) { throw error }
throw new AuthError(error instanceof Error ? error.message : "Unknown error");
}
} }
const setConfigToRedis = async (settingsObject: ClientSettings) => { const setConfigToRedis = async (settingsObject: ClientSettings) => {
try {
const decrpytUserSelection = await functionRetrieveUserSelection() const decrpytUserSelection = await functionRetrieveUserSelection()
if (!decrpytUserSelection) throw new Error("No user selection found"); if (!decrpytUserSelection) throw new AuthError("No user selection found");
const redisKey = decrpytUserSelection?.redisKey; const redisKey = decrpytUserSelection?.redisKey;
if (!redisKey) throw new Error("No redis key found"); if (!redisKey) throw new AuthError("No redis key found");
if (!settingsObject) throw new Error("No settings object provided"); if (!settingsObject) throw new AuthError("No settings object provided");
const oldData = await getCompleteFromRedis(); const oldData = await getCompleteFromRedis();
if (!oldData) throw new Error("No old data found in redis"); if (!oldData) throw new AuthError("No old data found in redis");
await setCompleteToRedis({ ...oldData, settings: settingsObject }); await setCompleteToRedis({ ...oldData, settings: settingsObject });
return true; return true;
} catch (error) {
if (error instanceof AuthError) { throw error }
throw new AuthError(error instanceof Error ? error.message : "Unknown error");
}
} }

View File

@ -3,28 +3,33 @@ import { redis } from "@/lib/redis";
import { functionRetrieveUserSelection } from "@/apifetchers/utils"; import { functionRetrieveUserSelection } from "@/apifetchers/utils";
import { ClientMenu } from "@/types/mutual/context/validations"; import { ClientMenu } from "@/types/mutual/context/validations";
import { getCompleteFromRedis, setCompleteToRedis } from "@/apifetchers/mutual/context/complete/fetch"; import { getCompleteFromRedis, setCompleteToRedis } from "@/apifetchers/mutual/context/complete/fetch";
import { AuthError } from "@/types/mutual/context/validations";
const getMenuFromRedis = async (): Promise<ClientMenu> => { const getMenuFromRedis = async (): Promise<ClientMenu> => {
try {
const decrpytUserSelection = await functionRetrieveUserSelection() const decrpytUserSelection = await functionRetrieveUserSelection()
const redisKey = decrpytUserSelection?.redisKey; const redisKey = decrpytUserSelection?.redisKey;
if (!redisKey) throw new Error("No redis key found"); if (!redisKey) throw new AuthError("No redis key found");
const result = await redis.get(`${redisKey}`); const result = await redis.get(`${redisKey}`);
if (!result) throw new Error("No data found in redis"); if (!result) throw new AuthError("No data found in redis");
const parsedResult = JSON.parse(result); const parsedResult = JSON.parse(result);
if (!parsedResult.menu) throw new Error("No menu found in redis"); if (!parsedResult.menu) throw new AuthError("No menu found in redis");
return parsedResult.menu; return parsedResult.menu;
} 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: ClientMenu) => {
try {
const decrpytUserSelection = await functionRetrieveUserSelection() const decrpytUserSelection = await functionRetrieveUserSelection()
if (!decrpytUserSelection) throw new Error("No user selection found"); if (!decrpytUserSelection) throw new AuthError("No user selection found");
const redisKey = decrpytUserSelection?.redisKey; const redisKey = decrpytUserSelection?.redisKey;
if (!redisKey) throw new Error("No redis key found"); if (!redisKey) throw new AuthError("No redis key found");
if (!menuObject) throw new Error("No menu object provided"); if (!menuObject) throw new AuthError("No menu object provided");
const oldData = await getCompleteFromRedis(); const oldData = await getCompleteFromRedis();
if (!oldData) throw new Error("No old data found in redis"); if (!oldData) throw new AuthError("No old data found in redis");
await setCompleteToRedis({ ...oldData, menu: menuObject }); await setCompleteToRedis({ ...oldData, menu: menuObject });
return true; return true;
} catch (error) { if (error instanceof AuthError) { throw error } else { throw new AuthError(error instanceof Error ? error.message : "Unknown error") } }
} }
export { getMenuFromRedis, setMenuToRedis }; export { getMenuFromRedis, setMenuToRedis };

View File

@ -3,17 +3,7 @@ import { redis } from "@/lib/redis";
import { functionRetrieveUserSelection } from "@/apifetchers/utils"; import { functionRetrieveUserSelection } from "@/apifetchers/utils";
import { ClientOnline } from "@/types/mutual/context/validations"; import { ClientOnline } from "@/types/mutual/context/validations";
import { getCompleteFromRedis, setCompleteToRedis } from "@/apifetchers/mutual/context/complete/fetch"; import { getCompleteFromRedis, setCompleteToRedis } from "@/apifetchers/mutual/context/complete/fetch";
import { AuthError } from "@/types/mutual/context/validations";
// Default online object to use as fallback
const defaultOnlineObject: ClientOnline = {
lang: "en",
userType: "occupant",
lastLogin: new Date(),
lastLogout: new Date(),
lastAction: new Date(),
lastPage: "/auth/login",
timezone: "GMT+3"
};
// Redis operation timeout (5 seconds) // Redis operation timeout (5 seconds)
const REDIS_TIMEOUT = 5000; const REDIS_TIMEOUT = 5000;
@ -24,72 +14,25 @@ const REDIS_TIMEOUT = 5000;
*/ */
const getOnlineFromRedis = async (): Promise<ClientOnline> => { const getOnlineFromRedis = async (): Promise<ClientOnline> => {
try { try {
console.log('Getting online state from Redis...');
// Get user selection with default fallback
let decrpytUserSelection;
try {
decrpytUserSelection = await functionRetrieveUserSelection();
console.log('User selection retrieved successfully');
} catch (error) {
console.error('Error retrieving user selection:', error);
return defaultOnlineObject;
}
const redisKey = decrpytUserSelection?.redisKey;
console.log('Redis key:', redisKey);
// If we have a default redisKey, return a default online object
if (!redisKey || redisKey === "default") {
console.log('Using default online object due to default/missing redisKey');
return defaultOnlineObject;
}
// Try to get data from Redis with timeout
let result; let result;
let decrpytUserSelection;
try { decrpytUserSelection = await functionRetrieveUserSelection() } catch (error) { throw new AuthError('Failed to retrieve user selection') }
const redisKey = decrpytUserSelection?.redisKey;
if (!redisKey) { throw new AuthError('No redis key found') }
if (redisKey === "default") { throw new AuthError('Invalid redis key') }
try { try {
// Create a promise that rejects after the timeout const timeoutPromise = new Promise((_, reject) => { setTimeout(() => reject(new Error('Redis operation timed out')), REDIS_TIMEOUT) });
const timeoutPromise = new Promise((_, reject) => { result = await Promise.race([redis.get(`${redisKey}`), timeoutPromise]) as string | null;
setTimeout(() => reject(new Error('Redis operation timed out')), REDIS_TIMEOUT); } catch (redisError) { throw new AuthError('Failed to access Redis data') }
});
// Race the Redis operation against the timeout if (!result) { throw new AuthError('No data found in redis') }
result = await Promise.race([
redis.get(`${redisKey}`),
timeoutPromise
]) as string | null;
console.log('Redis get operation completed');
} catch (redisError) {
console.error('Error accessing Redis:', redisError);
return defaultOnlineObject;
}
if (!result) {
console.log('No data found in Redis for key:', redisKey);
return defaultOnlineObject;
}
// Parse the result
try { try {
const parsedResult = JSON.parse(result); const parsedResult = JSON.parse(result);
console.log('Successfully parsed Redis result'); if (!parsedResult.online) { throw new AuthError('No online data found in redis') }
if (!parsedResult.online) {
console.warn('No online object in parsed result');
return defaultOnlineObject;
}
console.log('Returning online object from Redis');
return parsedResult.online; return parsedResult.online;
} catch (parseError) { } catch (parseError) { throw new AuthError('Invalid data format in redis') }
console.error('Error parsing Redis result:', parseError); } catch (error) { if (error instanceof AuthError) { throw error } else { throw new AuthError(error instanceof Error ? error.message : 'Unknown error') } }
return defaultOnlineObject;
}
} catch (error) {
console.error('Unexpected error in getOnlineFromRedis:', error);
return defaultOnlineObject;
}
} }
/** /**
@ -99,75 +42,23 @@ const getOnlineFromRedis = async (): Promise<ClientOnline> => {
*/ */
const setOnlineToRedis = async (onlineObject: ClientOnline): Promise<boolean> => { const setOnlineToRedis = async (onlineObject: ClientOnline): Promise<boolean> => {
try { try {
console.log('Setting online state in Redis:', onlineObject); if (!onlineObject) { throw new AuthError('No online object provided') }
// Validate input
if (!onlineObject) {
console.error('No online object provided');
return false;
}
// Get user selection
let decrpytUserSelection; let decrpytUserSelection;
try {
decrpytUserSelection = await functionRetrieveUserSelection();
console.log('User selection retrieved successfully');
} catch (error) {
console.error('Error retrieving user selection:', error);
return false;
}
if (!decrpytUserSelection) {
console.error('No user selection found');
return false;
}
const redisKey = decrpytUserSelection?.redisKey;
if (!redisKey) {
console.error('No redis key found in user selection');
return false;
}
console.log('Using Redis key:', redisKey);
// Get existing data from Redis
let oldData; let oldData;
try { decrpytUserSelection = await functionRetrieveUserSelection() } catch (error) { throw new AuthError('Failed to retrieve user selection') }
if (!decrpytUserSelection) { throw new AuthError('No user selection found') }
const redisKey = decrpytUserSelection?.redisKey;
if (!redisKey) { throw new AuthError('No redis key found') }
try { oldData = await getCompleteFromRedis() } catch (error) { throw new AuthError('Failed to retrieve existing data from Redis') }
if (!oldData) { throw new AuthError('No old data found in redis') }
try { try {
oldData = await getCompleteFromRedis(); const timeoutPromise = new Promise((_, reject) => { setTimeout(() => reject(new Error('Redis operation timed out')), REDIS_TIMEOUT) });
console.log('Retrieved existing data from Redis'); await Promise.race([setCompleteToRedis({ ...oldData, online: onlineObject }), timeoutPromise]);
} catch (error) {
console.error('Error getting complete data from Redis:', error);
return false;
}
if (!oldData) {
console.error('No existing data found in Redis');
return false;
}
// Update Redis with timeout
try {
// Create a promise that rejects after the timeout
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('Redis operation timed out')), REDIS_TIMEOUT);
});
// Race the Redis operation against the timeout
await Promise.race([
setCompleteToRedis({ ...oldData, online: onlineObject }),
timeoutPromise
]);
console.log('Successfully updated online state in Redis');
return true; return true;
} catch (redisError) { } catch (redisError) { throw new AuthError('Failed to update Redis data') }
console.error('Error updating Redis:', redisError); } catch (error) { if (error instanceof AuthError) throw error; throw new AuthError(error instanceof Error ? error.message : 'Unknown error') }
return false;
}
} catch (error) {
console.error('Unexpected error in setOnlineToRedis:', error);
return false;
}
} }
export { getOnlineFromRedis, setOnlineToRedis }; export { getOnlineFromRedis, setOnlineToRedis };

View File

@ -3,6 +3,7 @@ import NextCrypto from "next-crypto";
import { fetchDataWithToken } from "@/apifetchers/api-fetcher"; import { fetchDataWithToken } from "@/apifetchers/api-fetcher";
import { baseUrlAuth, baseUrlRestriction, tokenSecret } from "@/apifetchers/basics"; import { baseUrlAuth, baseUrlRestriction, tokenSecret } from "@/apifetchers/basics";
import { cookies } from "next/headers"; import { cookies } from "next/headers";
import { AuthError } from "@/types/mutual/context/validations";
const checkToken = `${baseUrlAuth}/authentication/token/check`; const checkToken = `${baseUrlAuth}/authentication/token/check`;
const pageValid = `${baseUrlRestriction}/restrictions/page/valid`; const pageValid = `${baseUrlRestriction}/restrictions/page/valid`;
@ -18,10 +19,7 @@ async function checkAccessTokenIsValid() {
try { try {
const response = await fetchDataWithToken(checkToken, {}, "GET", false); const response = await fetchDataWithToken(checkToken, {}, "GET", false);
return fetchResponseStatus(response); return fetchResponseStatus(response);
} catch (error) { } catch (error) { throw new AuthError("No access token found") }
console.error("Error checking token validity:", error);
return false;
}
} }
async function retrievePageList() { async function retrievePageList() {
@ -40,8 +38,7 @@ async function retrieveAccessToken() {
const encrpytAccessToken = cookieStore.get("eys-zzz")?.value || ""; const encrpytAccessToken = cookieStore.get("eys-zzz")?.value || "";
return await nextCrypto.decrypt(encrpytAccessToken) || ""; return await nextCrypto.decrypt(encrpytAccessToken) || "";
} }
catch (error) { console.error("Error retrieving access token:", error) } catch (error) { throw new AuthError("No access token found") }
return "";
} }
async function retrieveAccessObjects() { async function retrieveAccessObjects() {
@ -50,8 +47,7 @@ async function retrieveAccessObjects() {
const encrpytAccessObject = cookieStore.get("eys-yyy")?.value || ""; const encrpytAccessObject = cookieStore.get("eys-yyy")?.value || "";
return await nextCrypto.decrypt(encrpytAccessObject) || ""; return await nextCrypto.decrypt(encrpytAccessObject) || "";
} }
catch (error) { console.error("Error retrieving access objects:", error) } catch (error) { throw new AuthError("No access objects found") }
return "";
} }
export { export {

View File

@ -13,51 +13,20 @@ const functionRetrieveUserSelection = async () => {
try { try {
const cookieStore = await cookies(); const cookieStore = await cookies();
const encrpytUserSelection = cookieStore.get("eys-sel")?.value || ""; const encrpytUserSelection = cookieStore.get("eys-sel")?.value || "";
if (!encrpytUserSelection) { return { redisKey: "default", uuid: "", timestamp: new Date().toISOString() } }
if (!encrpytUserSelection) {
return {
redisKey: "default",
uuid: "",
timestamp: new Date().toISOString()
};
}
try { try {
const decrpytUserSelection = await nextCrypto.decrypt(encrpytUserSelection); const decrpytUserSelection = await nextCrypto.decrypt(encrpytUserSelection);
if (!decrpytUserSelection) { if (!decrpytUserSelection) { return { redisKey: "default", uuid: "", timestamp: new Date().toISOString() } }
return {
redisKey: "default",
uuid: "",
timestamp: new Date().toISOString()
};
}
return JSON.parse(decrpytUserSelection); return JSON.parse(decrpytUserSelection);
} catch (decryptError) { } catch (decryptError) { return { redisKey: "default", uuid: "", timestamp: new Date().toISOString() } }
return { } catch (error) { return { redisKey: "default", uuid: "", timestamp: new Date().toISOString() } }
redisKey: "default",
uuid: "",
timestamp: new Date().toISOString()
};
}
} catch (error) {
return {
redisKey: "default",
uuid: "",
timestamp: new Date().toISOString()
};
}
} }
const functionSetUserSelection = async (userSelection: any) => { const functionSetUserSelection = async (userSelection: any) => {
const cookieStore = await cookies(); const cookieStore = await cookies();
const encrpytUserSelection = await nextCrypto.encrypt(JSON.stringify(userSelection)); const encrpytUserSelection = await nextCrypto.encrypt(JSON.stringify(userSelection));
if (!encrpytUserSelection) throw new Error("No user selection found"); if (!encrpytUserSelection) throw new Error("No user selection found");
cookieStore.set({ cookieStore.set({ name: "eys-sel", value: encrpytUserSelection, ...cookieObject });
name: "eys-sel",
value: encrpytUserSelection,
...cookieObject,
});
} }
const functionRemoveUserSelection = async () => { const functionRemoveUserSelection = async () => {

View File

@ -3,19 +3,17 @@ import { AuthLayout } from "@/layouts/auth/layout";
import { AuthServerProps } from "@/validations/mutual/pages/props"; import { AuthServerProps } from "@/validations/mutual/pages/props";
import { LanguageTypes } from "@/validations/mutual/language/validations"; import { LanguageTypes } from "@/validations/mutual/language/validations";
import { checkAccessTokenIsValid } from "@/apifetchers/mutual/cookies/token"; import { checkAccessTokenIsValid } from "@/apifetchers/mutual/cookies/token";
import Login from "@/webPages/auth/login/page";
import Select from "@/webPages/auth/select/page";
import { getOnlineFromRedis } from "@/apifetchers/mutual/context/page/online/fetch"; import { getOnlineFromRedis } from "@/apifetchers/mutual/context/page/online/fetch";
import { redirect } from "next/navigation";
import Login from "@/webPages/auth/login/page";
const AuthPageSSR = async ({ params, searchParams }: AuthServerProps) => { const AuthPageSSR = async ({ params, searchParams }: AuthServerProps) => {
const awaitedParams = await params; const awaitedParams = await params;
const awaitedSearchParams = await searchParams; const awaitedSearchParams = await searchParams;
const pageUrlFromParams = `/${awaitedParams.page?.join("/")}` || "/login"; const pageUrlFromParams = `/${awaitedParams.page?.join("/")}` || "/login";
const tokenValid = await checkAccessTokenIsValid(); const tokenValid = await checkAccessTokenIsValid();
let FoundPage = <Login language={"en"} query={awaitedSearchParams} /> try { const online = await getOnlineFromRedis(); if (tokenValid && online) { redirect("/panel/dashboard") } } catch (error) { }
const online = await getOnlineFromRedis(); return <div className="flex flex-col items-center justify-center"><AuthLayout lang={"en"} page={<Login language={"en"} query={awaitedSearchParams} />} activePageUrl={pageUrlFromParams} /></div>
if (tokenValid && online) { FoundPage = <Select language={online?.lang as LanguageTypes} type={online?.userType} /> }
return <div className="flex flex-col items-center justify-center"><AuthLayout lang={online?.lang as LanguageTypes} page={FoundPage} activePageUrl={pageUrlFromParams} /></div>
} }
export default AuthPageSSR; export default AuthPageSSR;

View File

@ -2,25 +2,12 @@
import { MaindasboardPageProps } from "@/validations/mutual/dashboard/props"; import { MaindasboardPageProps } from "@/validations/mutual/dashboard/props";
import { DashboardLayout } from "@/layouts/dashboard/layout"; import { DashboardLayout } from "@/layouts/dashboard/layout";
import { redirect } from "next/navigation"; import { redirect } from "next/navigation";
import { fetchDataWithToken } from "@/apifetchers/api-fetcher"; import { checkAccessTokenIsValid } from "@/apifetchers/mutual/cookies/token";
import { baseUrlAuth } from "@/apifetchers/basics";
// Function to check token validity without trying to delete cookies
async function isTokenValid() {
try {
const checkToken = `${baseUrlAuth}/authentication/token/check`;
const response = await fetchDataWithToken(checkToken, {}, "GET", false);
return response?.status >= 200 && response?.status < 300;
} catch (error) {
console.error("Error checking token validity:", error);
return false;
}
}
const MainEnPage: React.FC<MaindasboardPageProps> = async ({ params, searchParams }) => { const MainEnPage: React.FC<MaindasboardPageProps> = async ({ params, searchParams }) => {
const parameters = await params; const parameters = await params;
const searchParameters = await searchParams; const searchParameters = await searchParams;
const tokenValid = await isTokenValid() const tokenValid = await checkAccessTokenIsValid()
if (!tokenValid) { redirect("/auth/login") } if (!tokenValid) { redirect("/auth/login") }
return ( return (
<div className="flex flex-col items-center justify-center"> <div className="flex flex-col items-center justify-center">

View File

@ -2,21 +2,74 @@ import {
getSelectionFromRedis, getSelectionFromRedis,
setSelectionToRedis, setSelectionToRedis,
} from "@/apifetchers/mutual/context/dash/selection/fetch"; } from "@/apifetchers/mutual/context/dash/selection/fetch";
import { AuthError } from "@/types/mutual/context/validations";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
export async function GET() { export async function GET() {
try {
const selection = await getSelectionFromRedis(); const selection = await getSelectionFromRedis();
return NextResponse.json({ return NextResponse.json({
status: 200, status: 200,
data: selection || null, data: selection || null,
}); });
} catch (error) {
if (error instanceof AuthError) {
// Return 401 Unauthorized for authentication errors
return new NextResponse(
JSON.stringify({
status: 401,
error: error.message,
}),
{
status: 401,
headers: { "Content-Type": "application/json" },
}
);
}
// For other errors, return 500 Internal Server Error
return new NextResponse(
JSON.stringify({
status: 500,
error: "Internal server error",
}),
{
status: 500,
headers: { "Content-Type": "application/json" },
}
);
}
} }
export async function POST(request: Request) { export async function POST(request: Request) {
try {
const selection = await request.json(); const selection = await request.json();
await setSelectionToRedis(selection); await setSelectionToRedis(selection);
return NextResponse.json({ return NextResponse.json({
status: 200, status: 200,
data: selection || null, data: selection || null,
}); });
} catch (error) {
if (error instanceof AuthError) {
return new NextResponse(
JSON.stringify({
status: 401,
error: error.message,
}),
{
status: 401,
headers: { "Content-Type": "application/json" },
}
);
}
return new NextResponse(
JSON.stringify({
status: 500,
error: "Internal server error",
}),
{
status: 500,
headers: { "Content-Type": "application/json" },
}
);
}
} }

View File

@ -2,15 +2,50 @@ import {
getSettingsFromRedis, getSettingsFromRedis,
setSettingsToRedis, setSettingsToRedis,
} from "@/apifetchers/mutual/context/dash/settings/fetch"; } from "@/apifetchers/mutual/context/dash/settings/fetch";
import { AuthError } from "@/types/mutual/context/validations";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
export async function GET() { export async function GET() {
try {
const settings = await getSettingsFromRedis(); const settings = await getSettingsFromRedis();
return NextResponse.json(settings); return NextResponse.json(settings);
} catch (error) {
if (error instanceof AuthError) {
// Return 401 Unauthorized for authentication errors
return new NextResponse(JSON.stringify({ error: error.message }), {
status: 401,
headers: { "Content-Type": "application/json" },
});
}
// For other errors, return 500 Internal Server Error
return new NextResponse(
JSON.stringify({ error: "Internal server error" }),
{
status: 500,
headers: { "Content-Type": "application/json" },
}
);
}
} }
export async function POST(request: Request) { export async function POST(request: Request) {
try {
const settings = await request.json(); const settings = await request.json();
await setSettingsToRedis(settings); await setSettingsToRedis(settings);
return NextResponse.json(settings); return NextResponse.json(settings);
} catch (error) {
if (error instanceof AuthError) {
return new NextResponse(JSON.stringify({ error: error.message }), {
status: 401,
headers: { "Content-Type": "application/json" },
});
}
return new NextResponse(
JSON.stringify({ error: "Internal server error" }),
{
status: 500,
headers: { "Content-Type": "application/json" },
}
);
}
} }

View File

@ -2,15 +2,50 @@ import {
getUserFromRedis, getUserFromRedis,
setUserToRedis, setUserToRedis,
} from "@/apifetchers/mutual/context/dash/user/fetch"; } from "@/apifetchers/mutual/context/dash/user/fetch";
import { AuthError } from "@/types/mutual/context/validations";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
export async function GET() { export async function GET() {
try {
const user = await getUserFromRedis(); const user = await getUserFromRedis();
return NextResponse.json(user); return NextResponse.json(user);
} catch (error) {
if (error instanceof AuthError) {
// Return 401 Unauthorized for authentication errors
return new NextResponse(JSON.stringify({ error: error.message }), {
status: 401,
headers: { "Content-Type": "application/json" },
});
}
// For other errors, return 500 Internal Server Error
return new NextResponse(
JSON.stringify({ error: "Internal server error" }),
{
status: 500,
headers: { "Content-Type": "application/json" },
}
);
}
} }
export async function POST(request: Request) { export async function POST(request: Request) {
try {
const user = await request.json(); const user = await request.json();
await setUserToRedis(user); await setUserToRedis(user);
return NextResponse.json(user); return NextResponse.json(user);
} catch (error) {
if (error instanceof AuthError) {
return new NextResponse(JSON.stringify({ error: error.message }), {
status: 401,
headers: { "Content-Type": "application/json" },
});
}
return new NextResponse(
JSON.stringify({ error: "Internal server error" }),
{
status: 500,
headers: { "Content-Type": "application/json" },
}
);
}
} }

View File

@ -2,15 +2,50 @@ import {
getConfigFromRedis, getConfigFromRedis,
setConfigToRedis, setConfigToRedis,
} from "@/apifetchers/mutual/context/page/config/fetch"; } from "@/apifetchers/mutual/context/page/config/fetch";
import { AuthError } from "@/types/mutual/context/validations";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
export async function GET() { export async function GET() {
try {
const config = await getConfigFromRedis(); const config = await getConfigFromRedis();
return NextResponse.json(config); return NextResponse.json(config);
} catch (error) {
if (error instanceof AuthError) {
// Return 401 Unauthorized for authentication errors
return new NextResponse(JSON.stringify({ error: error.message }), {
status: 401,
headers: { "Content-Type": "application/json" },
});
}
// For other errors, return 500 Internal Server Error
return new NextResponse(
JSON.stringify({ error: "Internal server error" }),
{
status: 500,
headers: { "Content-Type": "application/json" },
}
);
}
} }
export async function POST(request: Request) { export async function POST(request: Request) {
try {
const config = await request.json(); const config = await request.json();
await setConfigToRedis(config); await setConfigToRedis(config);
return NextResponse.json(config); return NextResponse.json(config);
} catch (error) {
if (error instanceof AuthError) {
return new NextResponse(JSON.stringify({ error: error.message }), {
status: 401,
headers: { "Content-Type": "application/json" },
});
}
return new NextResponse(
JSON.stringify({ error: "Internal server error" }),
{
status: 500,
headers: { "Content-Type": "application/json" },
}
);
}
} }

View File

@ -2,21 +2,74 @@ import {
getMenuFromRedis, getMenuFromRedis,
setMenuToRedis, setMenuToRedis,
} from "@/apifetchers/mutual/context/page/menu/fetch"; } from "@/apifetchers/mutual/context/page/menu/fetch";
import { AuthError } from "@/types/mutual/context/validations";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
export async function GET() { export async function GET() {
try {
const menu = await getMenuFromRedis(); const menu = await getMenuFromRedis();
return NextResponse.json({ return NextResponse.json({
status: 200, status: 200,
data: menu, data: menu,
}); });
} catch (error) {
if (error instanceof AuthError) {
// Return 401 Unauthorized for authentication errors
return new NextResponse(
JSON.stringify({
status: 401,
error: error.message,
}),
{
status: 401,
headers: { "Content-Type": "application/json" },
}
);
}
// For other errors, return 500 Internal Server Error
return new NextResponse(
JSON.stringify({
status: 500,
error: "Internal server error",
}),
{
status: 500,
headers: { "Content-Type": "application/json" },
}
);
}
} }
export async function POST(request: Request) { export async function POST(request: Request) {
try {
const menu = await request.json(); const menu = await request.json();
await setMenuToRedis(menu); await setMenuToRedis(menu);
return NextResponse.json({ return NextResponse.json({
status: 200, status: 200,
data: menu, data: menu,
}); });
} catch (error) {
if (error instanceof AuthError) {
return new NextResponse(
JSON.stringify({
status: 401,
error: error.message,
}),
{
status: 401,
headers: { "Content-Type": "application/json" },
}
);
}
return new NextResponse(
JSON.stringify({
status: 500,
error: "Internal server error",
}),
{
status: 500,
headers: { "Content-Type": "application/json" },
}
);
}
} }

View File

@ -2,21 +2,74 @@ import {
getOnlineFromRedis, getOnlineFromRedis,
setOnlineToRedis, setOnlineToRedis,
} from "@/apifetchers/mutual/context/page/online/fetch"; } from "@/apifetchers/mutual/context/page/online/fetch";
import { AuthError } from "@/types/mutual/context/validations";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
export async function GET() { export async function GET() {
try {
const online = await getOnlineFromRedis(); const online = await getOnlineFromRedis();
return NextResponse.json({ return NextResponse.json({
status: 200, status: 200,
data: online, data: online,
}); });
} catch (error) {
if (error instanceof AuthError) {
// Return 401 Unauthorized for authentication errors
return new NextResponse(
JSON.stringify({
status: 401,
error: error.message,
}),
{
status: 401,
headers: { "Content-Type": "application/json" },
}
);
}
// For other errors, return 500 Internal Server Error
return new NextResponse(
JSON.stringify({
status: 500,
error: "Internal server error",
}),
{
status: 500,
headers: { "Content-Type": "application/json" },
}
);
}
} }
export async function POST(request: Request) { export async function POST(request: Request) {
try {
const online = await request.json(); const online = await request.json();
await setOnlineToRedis(online); await setOnlineToRedis(online);
return NextResponse.json({ return NextResponse.json({
status: 200, status: 200,
data: online, data: online,
}); });
} catch (error) {
if (error instanceof AuthError) {
return new NextResponse(
JSON.stringify({
status: 401,
error: error.message,
}),
{
status: 401,
headers: { "Content-Type": "application/json" },
}
);
}
return new NextResponse(
JSON.stringify({
status: 500,
error: "Internal server error",
}),
{
status: 500,
headers: { "Content-Type": "application/json" },
}
);
}
} }

View File

@ -17,7 +17,7 @@ const translations = {
const HeaderComponent: FC<HeaderProps> = ({ const HeaderComponent: FC<HeaderProps> = ({
lang, activePageUrl, prefix, mode, lang, activePageUrl, prefix, mode,
onlineData, onlineLoading, onlineError, onlineData, onlineLoading, onlineError, refreshOnline, updateOnline,
userData, userLoading, userError, userData, userLoading, userError,
}) => { }) => {
return ( return (
@ -32,7 +32,10 @@ const HeaderComponent: FC<HeaderProps> = ({
<span className="font-semibold">{onlineData.lang || lang}</span> <span className="font-semibold">{onlineData.lang || lang}</span>
<span className="ml-2 text-xs bg-green-100 text-green-800 px-2 py-1 rounded-full">{onlineData.userType}</span> <span className="ml-2 text-xs bg-green-100 text-green-800 px-2 py-1 rounded-full">{onlineData.userType}</span>
</div> </div>
)}<LanguageSelectionComponent lang={lang} activePage={activePageUrl} prefix={prefix} /> )}<LanguageSelectionComponent
lang={lang} activePage={activePageUrl} prefix={prefix}
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline}
/>
</div> </div>
</div> </div>
); );

View File

@ -139,7 +139,6 @@ interface UseOnlineResult {
// Wrapper hook that adapts the generic hook to the expected interface // Wrapper hook that adapts the generic hook to the expected interface
export function useOnline(): UseOnlineResult { export function useOnline(): UseOnlineResult {
const { data, isLoading, error, refresh, update } = useContextOnline(); const { data, isLoading, error, refresh, update } = useContextOnline();
return { return {
onlineData: data, onlineData: data,
isLoading, isLoading,

View File

@ -10,9 +10,14 @@ interface LanguageSelectionComponentProps {
lang: LanguageTypes; lang: LanguageTypes;
activePage: string; activePage: string;
prefix: string; prefix: string;
onlineData: any;
onlineLoading: boolean;
onlineError: any;
refreshOnline: () => Promise<void>;
updateOnline: (newOnline: any) => Promise<boolean>;
} }
const LanguageSelectionComponent: React.FC<LanguageSelectionComponentProps> = ({ lang, activePage, prefix }) => { const LanguageSelectionComponent: React.FC<LanguageSelectionComponentProps> = ({ lang, activePage, prefix, onlineData, onlineLoading, onlineError, refreshOnline, updateOnline }) => {
const translations = langGet(lang, languageSelectionTranslation); const translations = langGet(lang, languageSelectionTranslation);
const getPageWithLocale = (locale: LanguageTypes): string => { return `${prefix}/${activePage}` } const getPageWithLocale = (locale: LanguageTypes): string => { return `${prefix}/${activePage}` }
const languageButtons = [ const languageButtons = [
@ -27,7 +32,8 @@ const LanguageSelectionComponent: React.FC<LanguageSelectionComponentProps> = ({
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent> <DropdownMenuContent>
{languageButtons.map((props, index) => ( {languageButtons.map((props, index) => (
<LanguageSelectionItem key={props.buttonsLang} {...props} /> <LanguageSelectionItem key={props.buttonsLang} {...props} onlineData={onlineData}
onlineLoading={onlineLoading} onlineError={onlineError} refreshOnline={refreshOnline} updateOnline={updateOnline} />
))} ))}
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>

View File

@ -1,25 +1,26 @@
'use client'; 'use client';
import { FC } from "react"; import { FC } from "react";
import { DropdownMenuItem } from "@/components/mutual/shadcnui/dropdown-menu"; import { DropdownMenuItem } from "@/components/mutual/shadcnui/dropdown-menu";
import { useRouter, usePathname, useSearchParams } from "next/navigation";
// Import the useOnline hook from the context file instead of the provider
import { useOnline } from "@/components/mutual/context/online/context";
import { ClientOnline } from "@/types/mutual/context/validations";
import Link from "next/link";
const RenderButtonComponent: FC<{ refUrl: string, innerText: string, buttonsLang: string }> = ( interface LanguageSelectionItemProps {
{ refUrl, innerText, buttonsLang }) => { activeLang: string,
const router = useRouter(); buttonsLang: string,
// Use the new hook properties: onlineData instead of online, refreshOnline and updateOnline refUrl: string,
const { onlineData, isLoading, error, refreshOnline, updateOnline } = useOnline(); innerText: string,
onlineData: any,
onlineLoading: boolean,
onlineError: any,
refreshOnline: () => Promise<void>,
updateOnline: (newOnline: any) => Promise<boolean>
}
const RenderButtonComponent: FC<LanguageSelectionItemProps> = (
{ activeLang, buttonsLang, refUrl, innerText, onlineData, onlineLoading, onlineError, refreshOnline, updateOnline }) => {
const setOnlineObject = async () => { const setOnlineObject = async () => {
if (!onlineData || isLoading) return; if (!onlineData || onlineLoading) return;
try { try {
console.log("Updating language to:", buttonsLang); console.log("Updating language to:", buttonsLang);
// Use the context hook to update online state
// This will update Redis, context API, and trigger re-renders
const success = await updateOnline({ const success = await updateOnline({
...onlineData, ...onlineData,
lang: buttonsLang, lang: buttonsLang,
@ -28,10 +29,7 @@ const RenderButtonComponent: FC<{ refUrl: string, innerText: string, buttonsLang
if (success) { if (success) {
console.log("Language updated successfully"); console.log("Language updated successfully");
// Refresh the online data to get the latest state
await refreshOnline(); await refreshOnline();
// Navigate to the new URL
router.push(refUrl);
} else { } else {
console.error("Failed to update language"); console.error("Failed to update language");
} }
@ -49,27 +47,20 @@ const RenderButtonComponent: FC<{ refUrl: string, innerText: string, buttonsLang
) )
} }
const LanguageSelectionItem: React.FC<LanguageSelectionItemProps> = ({ activeLang, buttonsLang, refUrl, innerText, onlineData, onlineLoading, onlineError, refreshOnline, updateOnline }) => {
const LanguageSelectionItem: React.FC<{
activeLang: string, buttonsLang: string, refUrl: string, innerText: string
}> = ({ activeLang, buttonsLang, refUrl, innerText }) => {
// Get the current online state to determine the actual current language
const { onlineData } = useOnline();
const pathname = usePathname();
const searchParams = useSearchParams();
const currentUrl = pathname + (searchParams.toString() ? `?${searchParams.toString()}` : "");
// Use the language from the online state if available, otherwise use the prop
const currentLang = onlineData?.lang || activeLang; const currentLang = onlineData?.lang || activeLang;
// Determine if this button should be active (not the current language)
const isActive = buttonsLang !== currentLang; const isActive = buttonsLang !== currentLang;
const RenderButtonProp = { const RenderButtonProp = {
refUrl, refUrl,
innerText, innerText,
buttonsLang activeLang,
buttonsLang,
onlineData,
onlineLoading,
onlineError,
refreshOnline,
updateOnline
} }
// Only render the button if it's not the current language // Only render the button if it's not the current language

View File

@ -1,7 +1,6 @@
'use server'; 'use server';
import { FC, Suspense } from "react"; import { FC, Suspense } from "react";
import { AuthLayoutProps } from "@/validations/mutual/auth/props"; import { AuthLayoutProps } from "@/validations/mutual/auth/props";
import LanguageSelectionComponent from "@/components/mutual/languageSelection/component";
const AuthLayout: FC<AuthLayoutProps> = async ({ lang, page, activePageUrl }) => { const AuthLayout: FC<AuthLayoutProps> = async ({ lang, page, activePageUrl }) => {
return ( return (
@ -13,7 +12,6 @@ const AuthLayout: FC<AuthLayoutProps> = async ({ lang, page, activePageUrl }) =>
</div> </div>
</div> </div>
<div className="w-3/4 text-black"> <div className="w-3/4 text-black">
<LanguageSelectionComponent lang={lang} activePage={activePageUrl} prefix={"/auth"} />
<Suspense fallback={<div>Loading...</div>}>{page}</Suspense> <Suspense fallback={<div>Loading...</div>}>{page}</Suspense>
</div> </div>
</div> </div>

View File

@ -35,87 +35,31 @@ interface ClientLayoutProps {
} }
const ClientLayout: FC<ClientLayoutProps> = ({ allProps }) => { const ClientLayout: FC<ClientLayoutProps> = ({ allProps }) => {
const { onlineData, isLoading: onlineLoading, error: onlineError } = useOnline(); const { onlineData, isLoading: onlineLoading, error: onlineError, refreshOnline, updateOnline } = useOnline();
const { userData, isLoading: userLoading, error: userError } = useUser(); const { userData, isLoading: userLoading, error: userError } = useUser();
const { availableApplications, isLoading: menuLoading, error: menuError, menuData, refreshMenu } = useMenu(); const { availableApplications, isLoading: menuLoading, error: menuError, menuData, refreshMenu } = useMenu();
const { selectionData, isLoading: selectionLoading, error: selectionError } = useSelection(); const { selectionData, isLoading: selectionLoading, error: selectionError } = useSelection();
const { configData, isLoading: configLoading, error: configError } = useConfig(); const { configData, isLoading: configLoading, error: configError } = useConfig();
console.log("RedisData", {
onlineData: {
isLoading: onlineLoading,
error: onlineError,
data: onlineData
},
userData: {
isLoading: userLoading,
error: userError,
data: userData
},
menuData: {
isLoading: menuLoading,
error: menuError,
data: menuData
},
selectionData: {
isLoading: selectionLoading,
error: selectionError,
data: selectionData
},
configData: {
isLoading: configLoading,
error: configError,
data: configData
}
})
useEffect(() => {
console.log('ClientLayout rendered with context providers');
return () => { console.log('ClientLayout unmounted'); };
}, []);
useEffect(() => {
console.log('OnlineData changed with context providers');
return () => { console.log('ClientLayout unmounted'); };
}, [onlineData]);
useEffect(() => {
console.log('UserData changed with context providers');
return () => { console.log('ClientLayout unmounted'); };
}, [userData]);
useEffect(() => {
console.log('MenuData changed with context providers');
return () => { console.log('ClientLayout unmounted'); };
}, [menuData]);
useEffect(() => {
console.log('SelectionData changed with context providers');
return () => { console.log('ClientLayout unmounted'); };
}, [selectionData]);
useEffect(() => {
console.log('ConfigData changed with context providers');
return () => { console.log('ClientLayout unmounted'); };
}, [configData]);
const useReloadWindow = () => { window.location.reload() }
return ( return (
<ClientProviders> <ClientProviders>
<div className="flex flex-col min-w-screen"> <div className="flex flex-col min-w-screen">
<HeaderComponent {...allProps} <HeaderComponent {...allProps}
useReloadWindow={useReloadWindow}
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError}
refreshOnline={refreshOnline} updateOnline={updateOnline}
userData={userData} userLoading={userLoading} userError={userError} userData={userData} userLoading={userLoading} userError={userError}
/> />
<MenuComponent {...allProps} <MenuComponent {...allProps}
useReloadWindow={useReloadWindow}
availableApplications={availableApplications} availableApplications={availableApplications}
onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError} onlineData={onlineData} onlineLoading={onlineLoading} onlineError={onlineError}
userData={userData} userLoading={userLoading} userError={userError} userData={userData} userLoading={userLoading} userError={userError}
selectionData={selectionData} selectionLoading={selectionLoading} selectionError={selectionError} selectionData={selectionData} selectionLoading={selectionLoading} selectionError={selectionError}
menuData={menuData} menuLoading={menuLoading} menuError={menuError} /> menuData={menuData} menuLoading={menuLoading} menuError={menuError} />
<ContentComponent {...allProps} <ContentComponent {...allProps}
useReloadWindow={useReloadWindow}
userData={userData} userLoading={userLoading} userError={userError} userData={userData} userLoading={userLoading} userError={userError}
selectionData={selectionData} selectionLoading={selectionLoading} selectionError={selectionError} selectionData={selectionData} selectionLoading={selectionLoading} selectionError={selectionError}
/> />
<FooterComponent {...allProps} <FooterComponent {...allProps}
useReloadWindow={useReloadWindow}
availableApplications={availableApplications} availableApplications={availableApplications}
configData={configData} configLoading={configLoading} configError={configError} configData={configData} configLoading={configLoading} configError={configError}
/> />

View File

@ -1,4 +1,10 @@
// From Redis objects // From Redis objects
export class AuthError extends Error {
constructor(message: string) {
super(message);
this.name = 'AuthError';
}
}
interface ClientOnline { interface ClientOnline {
lastLogin: Date; lastLogin: Date;

View File

@ -19,7 +19,6 @@ interface ContentProps {
lang: LanguageTypes; lang: LanguageTypes;
activePageUrl: string; activePageUrl: string;
mode?: ModeTypes; mode?: ModeTypes;
useReloadWindow?: () => void;
userData: any; userData: any;
userLoading: boolean; userLoading: boolean;
userError: any; userError: any;
@ -32,7 +31,6 @@ interface MenuProps {
lang: LanguageTypes; lang: LanguageTypes;
availableApplications: string[]; availableApplications: string[];
activePageUrl: string; activePageUrl: string;
useReloadWindow?: () => void;
onlineData: any; onlineData: any;
onlineLoading: boolean; onlineLoading: boolean;
onlineError: any; onlineError: any;
@ -51,7 +49,6 @@ interface FooterProps {
lang: LanguageTypes; lang: LanguageTypes;
availableApplications: string[]; availableApplications: string[];
activePageUrl: string; activePageUrl: string;
useReloadWindow?: () => void;
configData: any; configData: any;
configLoading: boolean; configLoading: boolean;
configError: any; configError: any;
@ -62,10 +59,11 @@ interface HeaderProps {
activePageUrl: string; activePageUrl: string;
prefix: string; prefix: string;
mode?: ModeTypes; mode?: ModeTypes;
useReloadWindow?: () => void;
onlineData: any; onlineData: any;
onlineLoading: boolean; onlineLoading: boolean;
onlineError: any; onlineError: any;
refreshOnline: () => Promise<void>;
updateOnline: (newOnline: any) => Promise<boolean>;
userData: any; userData: any;
userLoading: boolean; userLoading: boolean;
userError: any; userError: any;

View File

@ -20,12 +20,7 @@ export function loginHook(
if (response.status === 200) { if (response.status === 200) {
response.json().then((data) => { response.json().then((data) => {
setTimeout(() => { setTimeout(() => {
const userType = Router.push(`/panel/dashboard`);
data?.data?.user_type.toLowerCase() === "employee"
? "employee"
: "occupant";
const rediretUrl = `/auth/select?type=${userType}`;
Router.push(rediretUrl);
}, 100); }, 100);
}); });
} else { } else {

View File

@ -1,122 +0,0 @@
"use client";
import React, { useTransition, useState, useEffect } from "react";
import { useRouter } from "next/navigation";
import { Company } from "./types";
import { LoginEmployeeProps } from "./types";
import { selectEmployeeHook } from "./hook";
import { checkContextDashSelection } from "@/components/mutual/context/selection/context";
import { ClientSelection } from "@/types/mutual/context/validations";
const translation = {
en: {
companySelection: "Company Selection",
loggedInAs: "Logged in as",
duty: "Duty",
id: "ID",
noSelections: "No selections",
continue: "Continue",
select: "Select"
},
tr: {
companySelection: "Şirket Seçimi",
loggedInAs: "Giriş Yapan",
duty: "Görev",
id: "ID",
noSelections: "Seçim Yok",
continue: "Devam Et",
select: "Seç"
}
}
function LoginEmployee({
lang
}: LoginEmployeeProps) {
const [selectionListCopy, setSelectionListCopy] = useState<ClientSelection>({ selectionList: [], activeSelection: {} });
useEffect(() => {
checkContextDashSelection().then((selectionList) => {
if (!selectionList) throw new Error("No selection list found");
setSelectionListCopy(selectionList)
})
}, [])
const isArrayLengthOne = Array.isArray(selectionListCopy.selectionList) && selectionListCopy.selectionList.length === 1;
const isArrayLengthZero = Array.isArray(selectionListCopy.selectionList) && selectionListCopy.selectionList.length === 0;
const isArrayMoreThanOne = Array.isArray(selectionListCopy.selectionList) && selectionListCopy.selectionList.length > 1;
const Router = useRouter();
const [isPending, startTransition] = useTransition();
const [error, setError] = useState<string | null>(null);
const [jsonText, setJsonText] = useState<string | null>(null);
const onSubmitEmployee = async (uu_id: string) => { selectEmployeeHook(startTransition, { uuid: uu_id }, setError, setJsonText, Router, lang) };
// Render a company card with consistent styling
const CompanyCard = ({ company }: { company: Company }) => (
<div className="w-full p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-md transition-all">
<div className="flex flex-col" onClick={() => onSubmitEmployee(company.uu_id)}>
{/* Company name and type */}
<div className="flex items-center mb-2">
<h3 className="text-xl font-semibold text-gray-800">{company.public_name}</h3>
{company.company_type && (
<span className="ml-2 px-2 py-1 text-xs font-medium bg-blue-100 text-blue-800 rounded-full">
{company.company_type}
</span>
)}
</div>
{/* Duty information */}
{company.duty && (
<div className="mb-2 text-sm text-gray-600">
<span className="font-medium">{translation[lang].duty}:</span> {company.duty}
</div>
)}
{/* ID information */}
<div className="text-xs text-gray-500 mb-3">
<span className="font-medium">{translation[lang].id}:</span> {company.uu_id}
</div>
</div>
</div>
);
return (
<div className="w-full max-w-md mx-auto">
<h1 className="text-2xl font-bold text-gray-900 mb-2">{translation[lang].companySelection}</h1>
<p className="text-sm text-gray-500 mb-6">{translation[lang].loggedInAs}</p>
{/* No companies available */}
{isArrayLengthZero && (
<div className="text-center p-6 bg-gray-50 rounded-lg border border-gray-200">
<p className="text-gray-600">{translation[lang].noSelections}</p>
</div>
)}
{/* Single company */}
{isArrayLengthOne && <CompanyCard company={selectionListCopy.activeSelection as Company} />}
{/* Multiple companies */}
{isArrayMoreThanOne && (
<div className="space-y-3">
{selectionListCopy.selectionList.map((company, index) => (
<div key={company.uu_id || index} onClick={() => onSubmitEmployee(company.uu_id)}
className="cursor-pointer hover:translate-x-1 transition-transform"
><CompanyCard company={company as Company} /></div>
))}
</div>
)}
{/* Show error if any */}
{error && <p className="mt-4 text-sm text-red-600">{error}</p>}
{/* Loading indicator */}
{isPending && (
<div className="mt-4 flex justify-center">
<div className="animate-spin h-5 w-5 border-2 border-blue-600 rounded-full border-t-transparent"></div>
</div>
)}
</div>
);
}
export default LoginEmployee;

View File

@ -1,110 +0,0 @@
"use client";
import React, { useState, useTransition, useEffect } from "react";
import { useRouter } from "next/navigation";
import { LoginOccupantProps } from "./types";
import { selectOccupantHook } from "./hook";
import { checkContextDashSelection } from "@/components/mutual/context/selection/context";
import { ClientSelection } from "@/types/mutual/context/validations";
const translation = {
en: {
occupantSelection: "Occupant Selection",
loggedInAs: "Logged in as",
level: "Level",
noSelections: "No selections"
},
tr: {
occupantSelection: "İşçi Seçimi",
loggedInAs: "Giriş Yapan",
level: "Seviye",
noSelections: "Seçim Yok"
}
}
function LoginOccupant({ lang }: LoginOccupantProps) {
const Router = useRouter();
const [isPending, startTransition] = useTransition();
const [error, setError] = useState<string | null>(null);
const [jsonText, setJsonText] = useState<string | null>(null);
const [selectionList, setSelectionList] = useState<ClientSelection>({ selectionList: [], activeSelection: {} });
useEffect(() => {
checkContextDashSelection().then((selectionList) => {
if (!selectionList) throw new Error("No selection list found"); setSelectionList(selectionList);
})
}, [])
const onSubmitOccupant = async (data: any) => { selectOccupantHook(startTransition, data, setError, setJsonText, Router, lang) };
const isArrayLengthZero = Array.isArray(selectionList.selectionList) && selectionList.selectionList.length === 0;
const OccupantCard = ({ occupant, buildKey, idx }: { occupant: any, buildKey: string, idx: number }) => (
<div
key={`${buildKey}-${idx}`}
className="w-full p-4 mb-3 bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-md transition-all cursor-pointer hover:translate-x-1"
onClick={() => onSubmitOccupant({ build_living_space_uu_id: occupant.build_living_space_uu_id })}
>
<div className="flex flex-col">
<div className="flex items-center justify-between mb-2">
<h3 className="text-lg font-semibold text-gray-800">{occupant.description}</h3>
<span className="px-2 py-1 text-xs font-medium bg-blue-100 text-blue-800 rounded-full">
{occupant.code}
</span>
</div>
<div className="mb-1 text-sm text-gray-700 font-medium">
{occupant.part_name}
</div>
<div className="text-xs text-gray-500">
<span className="font-medium">{translation[lang].level}:</span> {occupant.part_level}
</div>
</div>
</div>
);
const BuildingSection = ({ building, buildKey }: { building: any, buildKey: string }) => (
<div key={buildKey} className="mb-6">
<div className="p-3 bg-gray-50 border border-gray-200 rounded-lg mb-3">
<h2 className="text-lg font-semibold text-gray-800 flex items-center">
<svg className="w-5 h-5 mr-2 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
</svg>
<span>{building.build_name}</span>
<span className="ml-2 px-2 py-0.5 text-xs bg-blue-100 text-blue-800 rounded-full">No: {building.build_no}</span>
</h2>
</div>
<div className="space-y-2">
{building.occupants.map((occupant: any, idx: number) => (
<OccupantCard key={idx} occupant={occupant} buildKey={buildKey} idx={idx} />
))}
</div>
</div>
);
return (
<div className="w-full max-w-md mx-auto">
<h1 className="text-2xl font-bold text-gray-900 mb-2">{translation[lang].occupantSelection}</h1>
<p className="text-sm text-gray-500 mb-6">{translation[lang].loggedInAs}</p>
{!isArrayLengthZero ? (
<div className="text-center p-6 bg-gray-50 rounded-lg border border-gray-200">
<p className="text-gray-600">{translation[lang].noSelections}</p>
</div>
) : (
<div>
{Object.keys(selectionList.selectionList).map((buildKey: string) => (
<BuildingSection
key={buildKey}
building={selectionList.activeSelection}
buildKey={buildKey}
/>
))}
</div>
)}
{error && <p className="mt-4 text-sm text-red-600">{error}</p>}
{isPending && (
<div className="mt-4 flex justify-center">
<div className="animate-spin h-5 w-5 border-2 border-blue-600 rounded-full border-t-transparent"></div>
</div>
)}
</div>
);
}
export default LoginOccupant;

View File

@ -1,81 +0,0 @@
import { LanguageTypes } from "@/validations/mutual/language/validations";
const afterLoginDirectUrl = () => {
return `/panel/dashboard`;
};
function selectEmployeeHook(
startTransition: any,
data: any,
setError: any,
setJsonText: any,
Router: any,
lang: LanguageTypes
) {
try {
const sendData = { ...data };
startTransition(() => {
fetch("/api/selection/employee", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(sendData),
})
.then((response) => {
if (response.status === 200) {
response.json().then((data) => {
console.log("data", data);
setTimeout(() => {
Router.push(afterLoginDirectUrl());
}, 100);
});
} else {
response.json().then((data) => {
setError(data?.message);
});
}
})
.catch(() => {});
});
} catch (error) {
setError("An error occurred during login");
}
}
function selectOccupantHook(
startTransition: any,
data: any,
setError: any,
setJsonText: any,
Router: any,
lang: LanguageTypes
) {
try {
const sendData = { ...data };
startTransition(() => {
fetch("/api/selection/occupant", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(sendData),
})
.then((response) => {
if (response.status === 200) {
response.json().then((data) => {
console.log("data", data);
setTimeout(() => {
Router.push(afterLoginDirectUrl());
}, 100);
});
} else {
response.json().then((data) => {
setError(data?.message);
});
}
})
.catch(() => {});
});
} catch (error) {
setError("An error occurred during login");
}
}
export { selectEmployeeHook, selectOccupantHook };

View File

@ -1,44 +0,0 @@
export const selectEmployeeTranslation = {
tr: {
companySelection: "Şirket Seçimi",
loggedInAs: "Çalışan olarak giriş yaptınız",
duty: "Görev",
id: "Kimlik",
noSelections: "Seçenek bulunamadı",
continue: "Devam et",
select: "Konut Seçimi",
},
en: {
companySelection: "Select your company",
loggedInAs: "You are logged in as an employee",
duty: "Duty",
id: "ID",
noSelections: "No selections available",
continue: "Continue",
select: "Select Occupant",
},
};
export const selectOccupantTranslation = {
tr: {
occupantSelection: "Daire Seçimi",
loggedInAs: "Kiracı olarak giriş yaptınız",
buildingInfo: "Bina Bilgisi",
level: "Kat",
noSelections: "Seçenek bulunamadı",
continue: "Devam et",
select: "Şirket Seçimi",
},
en: {
occupantSelection: "Select your occupant type",
loggedInAs: "You are logged in as an occupant",
buildingInfo: "Building Info",
level: "Level",
continue: "Continue",
noSelections: "No selections available",
select: "Select Company",
},
};

View File

@ -1,22 +0,0 @@
"use client";
import LoginOccupant from "./LoginOccupant";
import LoginEmployee from "./LoginEmployee";
import { SelectListProps } from "./types";
const Select: React.FC<SelectListProps> = ({ language, type }) => {
const isEmployeee = type.toLowerCase() == "employee";
const isOccupante = type.toLowerCase() == "occupant";
return (
<>
<div className="flex h-full min-h-[inherit] flex-col items-center justify-center gap-4">
<div className="w-full max-w-md rounded-lg bg-white p-8 shadow-md">
{isEmployeee && <LoginEmployee lang={language} />}
{isOccupante && <LoginOccupant lang={language} />}
</div>
</div>
</>
);
}
export default Select;

View File

@ -1,54 +0,0 @@
import { ClientSelection } from "@/types/mutual/context/validations";
import { LanguageTypes } from "@/validations/mutual/language/validations";
interface Company {
uu_id: string;
public_name: string;
company_type?: string;
company_address?: any;
duty?: string;
}
interface Occupant {
build_living_space_uu_id: string;
part_uu_id: string;
part_name: string;
part_level: number;
occupant_uu_id: string;
description: string;
code: string;
}
interface Building {
build_uu_id: string;
build_name: string;
build_no: string;
occupants: Occupant[];
}
interface BuildingMap {
[key: string]: Building;
}
interface SelectListProps {
language: LanguageTypes;
type: string;
}
interface LoginOccupantProps {
lang: LanguageTypes;
}
interface LoginEmployeeProps {
lang: LanguageTypes;
}
export type {
Company,
Occupant,
Building,
BuildingMap,
SelectListProps,
LoginOccupantProps,
LoginEmployeeProps,
};