user selection compoleted tested
This commit is contained in:
parent
a48e560ece
commit
9fb517fa15
|
|
@ -6,11 +6,13 @@ from .supers_events import (
|
||||||
SuperAccountRecordsUpdateEvent,
|
SuperAccountRecordsUpdateEvent,
|
||||||
SuperAccountRecordsDeleteEvent,
|
SuperAccountRecordsDeleteEvent,
|
||||||
)
|
)
|
||||||
|
from .flat_representative import FlatRepresentativeAccountRecordsListEvent
|
||||||
|
|
||||||
AccountRecordsRouterCluster = RouterCluster(name="AccountRecordsRouterCluster")
|
AccountRecordsRouterCluster = RouterCluster(name="AccountRecordsRouterCluster")
|
||||||
|
|
||||||
AccountRecordsListEventCluster = EventCluster(name="AccountRecordsListEventCluster", endpoint_uu_id=endpoints_index["AccountRecordsList"])
|
AccountRecordsListEventCluster = EventCluster(name="AccountRecordsListEventCluster", endpoint_uu_id=endpoints_index["AccountRecordsList"])
|
||||||
AccountRecordsListEventCluster.add_event(SuperAccountRecordsListEvent)
|
AccountRecordsListEventCluster.add_event(SuperAccountRecordsListEvent)
|
||||||
|
AccountRecordsListEventCluster.add_event(FlatRepresentativeAccountRecordsListEvent)
|
||||||
|
|
||||||
AccountRecordsCreateEventCluster = EventCluster(name="AccountRecordsCreateEventCluster", endpoint_uu_id=endpoints_index["AccountRecordsCreate"])
|
AccountRecordsCreateEventCluster = EventCluster(name="AccountRecordsCreateEventCluster", endpoint_uu_id=endpoints_index["AccountRecordsCreate"])
|
||||||
AccountRecordsCreateEventCluster.add_event(SuperAccountRecordsCreateEvent)
|
AccountRecordsCreateEventCluster.add_event(SuperAccountRecordsCreateEvent)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from Initializer.event_clusters import Event
|
||||||
|
from Validations.response import (
|
||||||
|
PaginateOnly,
|
||||||
|
Pagination,
|
||||||
|
PaginationResult,
|
||||||
|
PostgresResponseSingle,
|
||||||
|
PostgresResponse,
|
||||||
|
EndpointResponse
|
||||||
|
)
|
||||||
|
from Validations.defaults.validations import CommonHeaders
|
||||||
|
from Schemas import AccountRecords
|
||||||
|
from Extensions.Middlewares.token_provider import TokenProvider
|
||||||
|
|
||||||
|
|
||||||
|
# List all account records endpoint Flat Representative
|
||||||
|
FlatRepresentativeAccountRecordsListEvent = Event(
|
||||||
|
name="flat_representative_account_records_list",
|
||||||
|
key="7cb248d3-d75a-4d28-8be5-f147089ce654",
|
||||||
|
request_validator=None, # TODO: Add request validator
|
||||||
|
response_validator=None, # TODO: Add response validator
|
||||||
|
description="Flat Representative Account Records List all flat representative users endpoint",
|
||||||
|
)
|
||||||
|
|
||||||
|
class FlatRepresentativeAccountRecordsListPydantic:
|
||||||
|
uu_id: str
|
||||||
|
bank_date: datetime.datetime
|
||||||
|
currency_value: float
|
||||||
|
process_name: str
|
||||||
|
|
||||||
|
|
||||||
|
def flat_representative_account_records_list_callable(list_options: PaginateOnly, header: CommonHeaders):
|
||||||
|
list_options = PaginateOnly(**list_options.model_dump())
|
||||||
|
token_object = TokenProvider.get_dict_from_redis(token=header.token)
|
||||||
|
if not token_object.is_occupant:
|
||||||
|
raise Exception("Forbidden for employees")
|
||||||
|
|
||||||
|
pagination_query = {}
|
||||||
|
if list_options.query:
|
||||||
|
pagination_query = FlatRepresentativeAccountRecordsListPydantic(**list_options.query)
|
||||||
|
|
||||||
|
with AccountRecords.new_session() as db_session:
|
||||||
|
AccountRecords.set_session(db_session)
|
||||||
|
if pagination_query:
|
||||||
|
account_records_list = AccountRecords.query.filter(
|
||||||
|
*AccountRecords.convert(pagination_query),
|
||||||
|
AccountRecords.build_parts_id == token_object.selected_occupant.build_id
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
account_records_list = AccountRecords.query.filter(
|
||||||
|
AccountRecords.build_parts_id == token_object.selected_occupant.build_id
|
||||||
|
)
|
||||||
|
pagination = Pagination(data=account_records_list)
|
||||||
|
pagination.change(**list_options.model_dump())
|
||||||
|
pagination_result = PaginationResult(data=account_records_list, pagination=pagination, response_model=FlatRepresentativeAccountRecordsListPydantic)
|
||||||
|
return EndpointResponse(message="MSG0003-LIST", pagination_result=pagination_result).response
|
||||||
|
|
||||||
|
|
||||||
|
FlatRepresentativeAccountRecordsListEvent.event_callable = flat_representative_account_records_list_callable
|
||||||
|
|
@ -7,8 +7,7 @@ from config import api_config
|
||||||
from validations.request.auth.validations import (
|
from validations.request.auth.validations import (
|
||||||
RequestLogin,
|
RequestLogin,
|
||||||
RequestResetPassword,
|
RequestResetPassword,
|
||||||
RequestSelectLiving,
|
RequestSelect,
|
||||||
RequestSelectEmployee,
|
|
||||||
RequestCreatePassword,
|
RequestCreatePassword,
|
||||||
RequestChangePassword,
|
RequestChangePassword,
|
||||||
RequestForgotPasswordPhone,
|
RequestForgotPasswordPhone,
|
||||||
|
|
@ -44,7 +43,7 @@ auth_route_select_living = "AuthSelectLiving"
|
||||||
description="Selection of users company or occupant type",
|
description="Selection of users company or occupant type",
|
||||||
operation_id=endpoints_index[auth_route_select_living]
|
operation_id=endpoints_index[auth_route_select_living]
|
||||||
)
|
)
|
||||||
def select_living(data: Union[RequestSelectLiving, RequestSelectEmployee], headers: CommonHeaders = Depends(CommonHeaders.as_dependency)):
|
def select_living(data: Union[RequestSelect], headers: CommonHeaders = Depends(CommonHeaders.as_dependency)):
|
||||||
"""Select token object company or occupant type"""
|
"""Select token object company or occupant type"""
|
||||||
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
|
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
|
||||||
return AuthHandlers.LoginHandler.authentication_select_company_or_occupant_type(request=headers.request, data=data)
|
return AuthHandlers.LoginHandler.authentication_select_company_or_occupant_type(request=headers.request, data=data)
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,9 @@ from config import api_config
|
||||||
from Schemas import (
|
from Schemas import (
|
||||||
Users,
|
Users,
|
||||||
People,
|
People,
|
||||||
BuildLivingSpace,
|
Build,
|
||||||
BuildParts,
|
BuildParts,
|
||||||
|
BuildLivingSpace,
|
||||||
OccupantTypes,
|
OccupantTypes,
|
||||||
Employees,
|
Employees,
|
||||||
Addresses,
|
Addresses,
|
||||||
|
|
@ -78,6 +79,8 @@ class LoginHandler:
|
||||||
|
|
||||||
user_handler, other_domains_list, main_domain = UserHandlers(), [], ""
|
user_handler, other_domains_list, main_domain = UserHandlers(), [], ""
|
||||||
found_user = user_handler.check_user_exists(access_key=data.access_key, db_session=db_session)
|
found_user = user_handler.check_user_exists(access_key=data.access_key, db_session=db_session)
|
||||||
|
redis_handler = RedisHandlers()
|
||||||
|
|
||||||
with mongo_handler.collection(f"{str(found_user.related_company)}*Domain") as collection:
|
with mongo_handler.collection(f"{str(found_user.related_company)}*Domain") as collection:
|
||||||
result = collection.find_one({"user_uu_id": str(found_user.uu_id)})
|
result = collection.find_one({"user_uu_id": str(found_user.uu_id)})
|
||||||
if not result:
|
if not result:
|
||||||
|
|
@ -133,15 +136,13 @@ class LoginHandler:
|
||||||
person_uu_id=str(list_employees[0]["People.uu_id"]), request=dict(headers.request.headers), domain_list=other_domains_list,
|
person_uu_id=str(list_employees[0]["People.uu_id"]), request=dict(headers.request.headers), domain_list=other_domains_list,
|
||||||
companies_uu_id_list=companies_uu_id_list, companies_id_list=companies_id_list, duty_uu_id_list=duty_uu_id_list, duty_id_list=duty_id_list,
|
companies_uu_id_list=companies_uu_id_list, companies_id_list=companies_id_list, duty_uu_id_list=duty_uu_id_list, duty_id_list=duty_id_list,
|
||||||
).model_dump()
|
).model_dump()
|
||||||
employee_uuid = str(companies_list[0]["uu_id"])
|
|
||||||
print('employee_uuid', employee_uuid)
|
|
||||||
set_to_redis_dict = dict(
|
set_to_redis_dict = dict(
|
||||||
user=found_user, token=model_value, add_uuid=employee_uuid,
|
user=found_user, token=model_value,
|
||||||
header_info=dict(language=headers.language, domain=headers.domain, timezone=headers.timezone),
|
header_info=dict(language=headers.language, domain=headers.domain, timezone=headers.timezone),
|
||||||
)
|
)
|
||||||
user_dict = found_user.get_dict()
|
user_dict = found_user.get_dict()
|
||||||
person_dict = found_user.person.get_dict()
|
person_dict = found_user.person.get_dict()
|
||||||
if access_token := RedisHandlers().set_object_to_redis(**set_to_redis_dict):
|
if access_token := redis_handler.set_object_to_redis(**set_to_redis_dict):
|
||||||
return {
|
return {
|
||||||
"access_token": access_token,
|
"access_token": access_token,
|
||||||
"user_type": UserType.employee.name,
|
"user_type": UserType.employee.name,
|
||||||
|
|
@ -166,12 +167,15 @@ class LoginHandler:
|
||||||
language = headers.request.headers.get("language", "tr")
|
language = headers.request.headers.get("language", "tr")
|
||||||
domain = headers.request.headers.get("domain", None)
|
domain = headers.request.headers.get("domain", None)
|
||||||
timezone = headers.request.headers.get("tz", None) or "GMT+3"
|
timezone = headers.request.headers.get("tz", None) or "GMT+3"
|
||||||
|
BuildLivingSpace.set_session(db_session)
|
||||||
BuildParts.set_session(db_session)
|
BuildParts.set_session(db_session)
|
||||||
OccupantTypes.set_session(db_session)
|
OccupantTypes.set_session(db_session)
|
||||||
|
|
||||||
user_handler = UserHandlers()
|
user_handler = UserHandlers()
|
||||||
found_user = user_handler.check_user_exists(access_key=data.access_key, db_session=db_session)
|
found_user = user_handler.check_user_exists(access_key=data.access_key, db_session=db_session)
|
||||||
other_domains_list, main_domain = [], ""
|
other_domains_list, main_domain = [], ""
|
||||||
|
redis_handler = RedisHandlers()
|
||||||
|
|
||||||
with mongo_handler.collection(f"{str(found_user.related_company)}*Domain") as collection:
|
with mongo_handler.collection(f"{str(found_user.related_company)}*Domain") as collection:
|
||||||
result = collection.find_one({"user_uu_id": str(found_user.uu_id)})
|
result = collection.find_one({"user_uu_id": str(found_user.uu_id)})
|
||||||
if not result:
|
if not result:
|
||||||
|
|
@ -189,6 +193,10 @@ class LoginHandler:
|
||||||
|
|
||||||
if not living_spaces:
|
if not living_spaces:
|
||||||
raise ValueError("EYS_0006")
|
raise ValueError("EYS_0006")
|
||||||
|
|
||||||
|
user_dict = found_user.get_dict()
|
||||||
|
person_dict = found_user.person.get_dict()
|
||||||
|
|
||||||
for living_space in living_spaces:
|
for living_space in living_spaces:
|
||||||
build_part = BuildParts.query.filter(BuildParts.id == living_space.build_parts_id).first()
|
build_part = BuildParts.query.filter(BuildParts.id == living_space.build_parts_id).first()
|
||||||
if not build_part:
|
if not build_part:
|
||||||
|
|
@ -197,28 +205,40 @@ class LoginHandler:
|
||||||
build = build_part.buildings
|
build = build_part.buildings
|
||||||
occupant_type = OccupantTypes.query.filter(OccupantTypes.id == living_space.occupant_type_id).first()
|
occupant_type = OccupantTypes.query.filter(OccupantTypes.id == living_space.occupant_type_id).first()
|
||||||
occupant_data = {
|
occupant_data = {
|
||||||
"build_living_space_uu_id": str(living_space.uu_id), "part_uu_id": str(build_part.uu_id), "part_name": build_part.part_name(), "part_level": build_part.part_level,
|
"build_living_space_uu_id": str(living_space.uu_id), "part_uu_id": str(build_part.uu_id), "part_name": build_part.part_name(db=db_session),
|
||||||
"occupant_uu_id": str(occupant_type.uu_id), "description": occupant_type.occupant_description, "code": occupant_type.occupant_code,
|
"part_level": build_part.part_level, "occupant_uu_id": str(occupant_type.uu_id), "description": occupant_type.occupant_description,
|
||||||
|
"code": occupant_type.occupant_code,
|
||||||
}
|
}
|
||||||
|
|
||||||
build_key = str(build.uu_id)
|
build_key = str(build.uu_id)
|
||||||
if build_key not in occupants_selection_dict:
|
if build_key not in occupants_selection_dict:
|
||||||
occupants_selection_dict[build_key] = {"build_uu_id": build_key, "build_name": build.build_name, "build_no": build.build_no, "occupants": [occupant_data],}
|
occupants_selection_dict[build_key] = {"build_uu_id": build_key, "build_name": build.build_name, "build_no": build.build_no, "occupants": [occupant_data]}
|
||||||
else:
|
else:
|
||||||
occupants_selection_dict[build_key]["occupants"].append(occupant_data)
|
occupants_selection_dict[build_key]["occupants"].append(occupant_data)
|
||||||
|
|
||||||
person = found_user.person
|
person = found_user.person
|
||||||
model_value = OccupantTokenObject(
|
model_value = OccupantTokenObject(
|
||||||
user_type=UserType.occupant.value, user_uu_id=str(found_user.uu_id), user_id=found_user.id, person_id=person.id,
|
user_type=UserType.occupant.value, user_uu_id=str(found_user.uu_id), user_id=found_user.id, person_id=person.id,
|
||||||
person_uu_id=str(person.uu_id), domain_list=other_domains_list, request=dict(request.headers), available_occupants=occupants_selection_dict,
|
person_uu_id=str(person.uu_id), domain_list=other_domains_list, request=dict(headers.request.headers), available_occupants=occupants_selection_dict,
|
||||||
).model_dump()
|
).model_dump()
|
||||||
redis_handler = RedisHandlers()
|
|
||||||
if access_token := redis_handler.set_object_to_redis(
|
set_redis_dict = dict(user=found_user, token=model_value, header_info=dict(language=language, domain=domain, timezone=timezone))
|
||||||
user=found_user, token=model_value, add_uuid=living_space.uu_id,
|
if access_token := redis_handler.set_object_to_redis(**set_redis_dict):
|
||||||
header_info=dict(language=language, domain=domain, timezone=timezone)
|
return {
|
||||||
):
|
"access_token": access_token,
|
||||||
return {"access_token": access_token, "user_type": UserType.occupant.name, "selection_list": occupants_selection_dict}
|
"user_type": UserType.occupant.name,
|
||||||
raise ValueError("Something went wrong")
|
"user": {
|
||||||
|
"uuid": user_dict["uu_id"], "avatar": user_dict["avatar"], "email": user_dict["email"], "phone_number": user_dict["phone_number"], "user_tag": user_dict["user_tag"],
|
||||||
|
"password_expiry_begins": str(arrow.get(user_dict["password_expiry_begins"]).shift(days=int(user_dict["password_expires_day"]))),
|
||||||
|
"person": {
|
||||||
|
"uuid": person_dict["uu_id"], "firstname": person_dict["firstname"], "surname": person_dict["surname"],
|
||||||
|
"middle_name": person_dict["middle_name"], "sex_code": person_dict["sex_code"], "person_tag": person_dict["person_tag"],
|
||||||
|
"country_code": person_dict["country_code"], "birth_date": person_dict["birth_date"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"selection_list": occupants_selection_dict,
|
||||||
|
}
|
||||||
|
raise ValueError("Something went wrong")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def authentication_login_with_domain_and_creds(cls, headers: CommonHeaders, data: Any):
|
def authentication_login_with_domain_and_creds(cls, headers: CommonHeaders, data: Any):
|
||||||
|
|
@ -264,10 +284,12 @@ class LoginHandler:
|
||||||
with Users.new_session() as db_session:
|
with Users.new_session() as db_session:
|
||||||
if data.uuid not in token_dict.companies_uu_id_list:
|
if data.uuid not in token_dict.companies_uu_id_list:
|
||||||
ValueError("EYS_0011")
|
ValueError("EYS_0011")
|
||||||
|
|
||||||
list_of_returns = (
|
list_of_returns = (
|
||||||
Employees.id, Employees.uu_id, People.id, People.uu_id, Users.id, Users.uu_id, Companies.id, Companies.uu_id,
|
Employees.id, Employees.uu_id, People.id, People.uu_id, Users.id, Users.uu_id, Companies.id, Companies.uu_id, Companies.public_name, Companies.company_type,
|
||||||
Departments.id, Departments.uu_id, Duty.id, Duty.uu_id, Addresses.id, Addresses.letter_address, Staff.id, Staff.uu_id,
|
Departments.id, Departments.uu_id, Duty.id, Duty.uu_id, Addresses.id, Addresses.letter_address, Staff.id, Staff.uu_id, Duty.duty_name,
|
||||||
Duties.id, Duties.uu_id,
|
Duties.id, Duties.uu_id, BuildParts.id, BuildParts.uu_id, BuildParts.part_name, BuildParts.part_level, BuildParts.part_code,
|
||||||
|
OccupantTypes.id, OccupantTypes.uu_id, OccupantTypes.occupant_type, OccupantTypes.occupant_description, Addresses.letter_address
|
||||||
)
|
)
|
||||||
|
|
||||||
selected_company_query = db_session.query(*list_of_returns
|
selected_company_query = db_session.query(*list_of_returns
|
||||||
|
|
@ -298,82 +320,76 @@ class LoginHandler:
|
||||||
filter_endpoints_and_events = db_session.query(EndpointRestriction.operation_uu_id, Events.function_code
|
filter_endpoints_and_events = db_session.query(EndpointRestriction.operation_uu_id, Events.function_code
|
||||||
).join(EndpointRestriction, EndpointRestriction.id == Events.endpoint_id).filter().all()
|
).join(EndpointRestriction, EndpointRestriction.id == Events.endpoint_id).filter().all()
|
||||||
reachable_event_codes = {endpoint_name: function_code for endpoint_name, function_code in filter_endpoints_and_events}
|
reachable_event_codes = {endpoint_name: function_code for endpoint_name, function_code in filter_endpoints_and_events}
|
||||||
|
|
||||||
# Get reachable applications
|
# Get reachable applications
|
||||||
reachable_app_codes = Application2Employee.get_application_codes(employee_id=int(result_with_keys_dict['Employees.id']), db=db_session)
|
reachable_app_codes = Application2Employee.get_application_codes(employee_id=int(result_with_keys_dict['Employees.id']), db=db_session)
|
||||||
|
|
||||||
company_token = CompanyToken(
|
add_company = {
|
||||||
company_uu_id=str(result_with_keys_dict['Companies.uu_id']),
|
"uu_id": str(result_with_keys_dict["Employees.uu_id"]),
|
||||||
company_id=int(result_with_keys_dict['Companies.id']),
|
"public_name": result_with_keys_dict["Companies.public_name"],
|
||||||
department_id=int(result_with_keys_dict['Departments.id']),
|
"company_type": result_with_keys_dict["Companies.company_type"],
|
||||||
department_uu_id=str(result_with_keys_dict['Departments.uu_id']),
|
"company_address": result_with_keys_dict["Addresses.letter_address"],
|
||||||
duty_id=int(result_with_keys_dict['Duty.id']),
|
"duty": result_with_keys_dict["Duty.duty_name"],
|
||||||
duty_uu_id=str(result_with_keys_dict['Duty.uu_id']),
|
"company_uuid": str(result_with_keys_dict["Companies.uu_id"])
|
||||||
bulk_duties_id=int(result_with_keys_dict['Duties.id']),
|
}
|
||||||
staff_id=int(result_with_keys_dict['Staff.id']),
|
|
||||||
staff_uu_id=str(result_with_keys_dict['Staff.uu_id']),
|
|
||||||
employee_id=int(result_with_keys_dict['Employees.id']),
|
|
||||||
employee_uu_id=str(result_with_keys_dict['Employees.uu_id']),
|
|
||||||
reachable_event_codes=reachable_event_codes,
|
|
||||||
reachable_app_codes=reachable_app_codes,
|
|
||||||
)
|
|
||||||
redis_handler = RedisHandlers()
|
redis_handler = RedisHandlers()
|
||||||
redis_result = redis_handler.update_token_at_redis(
|
user_uu_id = Users.query.filter(Users.person_id == result_with_keys_dict['People.id']).first().uu_id
|
||||||
token=access_token, add_payload=company_token, add_uuid=str(result_with_keys_dict['Employees.uu_id'])
|
redis_result = redis_handler.update_token_at_redis(token=access_token, add_payload=add_company, user_uuid=user_uu_id)
|
||||||
)
|
|
||||||
return {"selected_uu_id": data.uuid}
|
return {"selected_uu_id": data.uuid}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def handle_occupant_selection(cls, access_token: str, data: Any, token_dict: TokenDictType):
|
def handle_occupant_selection(cls, access_token: str, data: Any, token_dict: TokenDictType):
|
||||||
"""Handle occupant type selection"""
|
"""Handle occupant type selection"""
|
||||||
with BuildLivingSpace.new_session() as db:
|
with BuildLivingSpace.new_session() as db:
|
||||||
# Get selected occupant type
|
BuildLivingSpace.set_session(db)
|
||||||
selected_build_living_space: BuildLivingSpace = BuildLivingSpace.filter_one(BuildLivingSpace.uu_id == data.build_living_space_uu_id, db=db).data
|
BuildParts.set_session(db)
|
||||||
if not selected_build_living_space:
|
Users.set_session(db)
|
||||||
|
|
||||||
|
list_of_returns = (
|
||||||
|
BuildLivingSpace.id, BuildLivingSpace.uu_id, OccupantTypes.id, OccupantTypes.uu_id, OccupantTypes.occupant_type, BuildParts.id, BuildParts.uu_id, Build.id, Build.uu_id,
|
||||||
|
BuildParts.id, BuildParts.part_level, OccupantTypes.occupant_description, OccupantTypes.occupant_code, People.id, People.uu_id
|
||||||
|
)
|
||||||
|
|
||||||
|
selected_build_living_space_query = db.query(*list_of_returns
|
||||||
|
).join(OccupantTypes, OccupantTypes.id == BuildLivingSpace.occupant_type_id
|
||||||
|
).join(BuildParts, BuildParts.id == BuildLivingSpace.build_parts_id
|
||||||
|
).join(Build, Build.id == BuildParts.build_id
|
||||||
|
).join(People, People.id == BuildLivingSpace.person_id
|
||||||
|
).filter(BuildLivingSpace.uu_id == data.uuid)
|
||||||
|
|
||||||
|
selected_build_living_space_first = selected_build_living_space_query.first()
|
||||||
|
if not selected_build_living_space_first:
|
||||||
raise ValueError("EYS_0012")
|
raise ValueError("EYS_0012")
|
||||||
|
|
||||||
|
result_with_keys_dict = {}
|
||||||
|
for ix, selected_build_living_space_item in enumerate(selected_build_living_space_first):
|
||||||
|
result_with_keys_dict[str(list_of_returns[ix])] = selected_build_living_space_item
|
||||||
|
|
||||||
# Get reachable events
|
filter_endpoints_and_events = db.query(EndpointRestriction.operation_uu_id, Events.function_code
|
||||||
reachable_event_codes = Event2Occupant.get_event_codes(build_living_space_id=selected_build_living_space.id, db=db)
|
).join(EndpointRestriction, EndpointRestriction.id == Events.endpoint_id).filter().all()
|
||||||
occupant_type = OccupantTypes.filter_one_system(OccupantTypes.id == selected_build_living_space.occupant_type_id, db=db).data
|
reachable_event_codes = {endpoint_name: function_code for endpoint_name, function_code in filter_endpoints_and_events}
|
||||||
build_part = BuildParts.filter_one(BuildParts.id == selected_build_living_space.build_parts_id, db=db)
|
|
||||||
build = build_part.buildings
|
|
||||||
reachable_app_codes = Application2Occupant.get_application_codes(build_living_space_id=selected_build_living_space.id, db=db)
|
|
||||||
# responsible_employee = Employees.filter_one(
|
|
||||||
# Employees.id == build_part.responsible_employee_id,
|
|
||||||
# db=db,
|
|
||||||
# ).data
|
|
||||||
# related_company = RelationshipEmployee2Build.filter_one(
|
|
||||||
# RelationshipEmployee2Build.member_id == build.id,
|
|
||||||
# db=db,
|
|
||||||
# ).data
|
|
||||||
# Get company
|
|
||||||
# company_related = Companies.filter_one(
|
|
||||||
# Companies.id == related_company.company_id,
|
|
||||||
# db=db,
|
|
||||||
# ).data
|
|
||||||
|
|
||||||
# Create occupant token
|
# Get reachable applications
|
||||||
occupant_token = OccupantToken(
|
reachable_app_codes = Application2Occupant.get_application_codes(build_living_space_id=selected_build_living_space_first.id, db=db)
|
||||||
living_space_id=selected_build_living_space.id,
|
|
||||||
living_space_uu_id=selected_build_living_space.uu_id.__str__(),
|
build_part = BuildParts.query.filter(BuildParts.id == result_with_keys_dict['BuildParts.id']).first()
|
||||||
occupant_type_id=occupant_type.id,
|
if not build_part:
|
||||||
occupant_type_uu_id=occupant_type.uu_id.__str__(),
|
raise ValueError("EYS_0013")
|
||||||
occupant_type=occupant_type.occupant_type,
|
|
||||||
build_id=build.id,
|
add_build_living_space = {
|
||||||
build_uuid=build.uu_id.__str__(),
|
"build_living_space_uu_id": str(data.uuid),
|
||||||
build_part_id=build_part.id,
|
"part_uu_id": str(result_with_keys_dict['BuildParts.uu_id']),
|
||||||
build_part_uuid=build_part.uu_id.__str__(),
|
"part_name": build_part.part_name(db=db),
|
||||||
# responsible_employee_id=responsible_employee.id,
|
"part_level": result_with_keys_dict['BuildParts.part_level'],
|
||||||
# responsible_employee_uuid=responsible_employee.uu_id.__str__(),
|
"occupant_uu_id": str(result_with_keys_dict['OccupantTypes.uu_id']),
|
||||||
# responsible_company_id=company_related.id,
|
"description": result_with_keys_dict['OccupantTypes.occupant_description'],
|
||||||
# responsible_company_uuid=company_related.uu_id.__str__(),
|
"code": result_with_keys_dict['OccupantTypes.occupant_code']
|
||||||
reachable_event_codes=reachable_event_codes,
|
}
|
||||||
reachable_app_codes=reachable_app_codes,
|
|
||||||
)
|
|
||||||
redis_handler = RedisHandlers()
|
redis_handler = RedisHandlers()
|
||||||
redis_handler.update_token_at_redis(
|
|
||||||
token=access_token, add_payload=occupant_token, add_uuid=occupant_token.living_space_uu_id
|
user_uu_id = Users.query.filter(Users.person_id == result_with_keys_dict['People.id']).first().uu_id
|
||||||
)
|
redis_handler.update_token_at_redis(token=access_token, add_payload=add_build_living_space, user_uuid=user_uu_id)
|
||||||
return {"selected_uu_id": occupant_token.living_space_uu_id}
|
return {"selected_uu_id": data.uuid}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def authentication_select_company_or_occupant_type(cls, request: Any, data: Any):
|
def authentication_select_company_or_occupant_type(cls, request: Any, data: Any):
|
||||||
|
|
@ -469,3 +485,30 @@ class AuthHandlers:
|
||||||
|
|
||||||
LoginHandler: LoginHandler = LoginHandler()
|
LoginHandler: LoginHandler = LoginHandler()
|
||||||
PasswordHandler: PasswordHandler = PasswordHandler()
|
PasswordHandler: PasswordHandler = PasswordHandler()
|
||||||
|
|
||||||
|
|
||||||
|
# Get selected occupant type
|
||||||
|
# selected_build_living_space: BuildLivingSpace = BuildLivingSpace.filter_one(BuildLivingSpace.uu_id == data.build_living_space_uu_id, db=db).data
|
||||||
|
# if not selected_build_living_space:
|
||||||
|
# raise ValueError("EYS_0012")
|
||||||
|
|
||||||
|
# occupant_type = OccupantTypes.filter_one_system(OccupantTypes.id == selected_build_living_space.occupant_type_id, db=db).data
|
||||||
|
# build_part = BuildParts.filter_one(BuildParts.id == selected_build_living_space.build_parts_id, db=db)
|
||||||
|
# build = build_part.buildings
|
||||||
|
# reachable_app_codes = Application2Occupant.get_application_codes(build_living_space_id=selected_build_living_space.id, db=db)
|
||||||
|
# responsible_employee = Employees.filter_one(
|
||||||
|
# Employees.id == build_part.responsible_employee_id,
|
||||||
|
# db=db,
|
||||||
|
# ).data
|
||||||
|
# related_company = RelationshipEmployee2Build.filter_one(
|
||||||
|
# RelationshipEmployee2Build.member_id == build.id,
|
||||||
|
# db=db,
|
||||||
|
# ).data
|
||||||
|
# Get company
|
||||||
|
# company_related = Companies.filter_one(
|
||||||
|
# Companies.id == related_company.company_id,
|
||||||
|
# db=db,
|
||||||
|
# ).data
|
||||||
|
|
||||||
|
# Get reachable events
|
||||||
|
# reachable_event_codes = Event2Occupant.get_event_codes(build_living_space_id=selected_build_living_space.id, db=db)
|
||||||
|
|
@ -14,7 +14,7 @@ class RequestVerifyOTP(BaseModel):
|
||||||
otp: str
|
otp: str
|
||||||
|
|
||||||
|
|
||||||
class RequestSelectEmployee(BaseModel):
|
class RequestSelect(BaseModel):
|
||||||
uuid: str
|
uuid: str
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -23,10 +23,6 @@ class RequestResetPassword(BaseModel):
|
||||||
password: str
|
password: str
|
||||||
re_password: str
|
re_password: str
|
||||||
|
|
||||||
|
|
||||||
class RequestSelectLiving(BaseModel):
|
|
||||||
uuid: str
|
|
||||||
|
|
||||||
class RequestCreatePassword(BaseModel):
|
class RequestCreatePassword(BaseModel):
|
||||||
password_token: str
|
password_token: str
|
||||||
password: str
|
password: str
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from Initializer.event_clusters import Event
|
||||||
|
from Validations.response import (
|
||||||
|
PaginateOnly,
|
||||||
|
Pagination,
|
||||||
|
PaginationResult,
|
||||||
|
PostgresResponseSingle,
|
||||||
|
PostgresResponse,
|
||||||
|
EndpointResponse
|
||||||
|
)
|
||||||
|
from Validations.defaults.validations import CommonHeaders
|
||||||
|
from Schemas import People
|
||||||
|
from Extensions.Middlewares.token_provider import TokenProvider
|
||||||
|
|
||||||
|
|
||||||
|
# List all people endpoint Flat Tenant
|
||||||
|
FlatTenantPeopleListEvent = Event(
|
||||||
|
name="flat_tenant_people_list",
|
||||||
|
key="7cb248d3-d75a-4d28-8be5-f147089ce654",
|
||||||
|
request_validator=None, # TODO: Add request validator
|
||||||
|
response_validator=None, # TODO: Add response validator
|
||||||
|
description="Flat Tenant People List all flat tenant users endpoint",
|
||||||
|
)
|
||||||
|
|
||||||
|
class FlatTenantPeopleListPydantic:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def flat_tenant_people_list_callable(list_options: PaginateOnly, header: CommonHeaders):
|
||||||
|
list_options = PaginateOnly(**list_options.model_dump())
|
||||||
|
token_object = TokenProvider.get_dict_from_redis(token=header.token)
|
||||||
|
if not token_object.is_occupant:
|
||||||
|
raise Exception("Forbidden for employees")
|
||||||
|
|
||||||
|
pagination_query = {}
|
||||||
|
if list_options.query:
|
||||||
|
pagination_query = FlatTenantPeopleListPydantic(**list_options.query)
|
||||||
|
|
||||||
|
with People.new_session() as db_session:
|
||||||
|
People.set_session(db_session)
|
||||||
|
if pagination_query:
|
||||||
|
people_list = People.query.filter(
|
||||||
|
*People.convert(pagination_query),
|
||||||
|
People.build_parts_id == token_object.selected_occupant.build_id
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
people_list = People.query.filter(
|
||||||
|
People.build_parts_id == token_object.selected_occupant.build_id
|
||||||
|
)
|
||||||
|
pagination = Pagination(data=people_list)
|
||||||
|
pagination.change(**list_options.model_dump())
|
||||||
|
pagination_result = PaginationResult(data=people_list, pagination=pagination, response_model=FlatTenantPeopleListPydantic)
|
||||||
|
return EndpointResponse(message="MSG0003-LIST", pagination_result=pagination_result).response
|
||||||
|
|
||||||
|
|
||||||
|
FlatTenantPeopleListEvent.event_callable = flat_tenant_people_list_callable
|
||||||
|
|
@ -36,6 +36,7 @@ class TokenProvider:
|
||||||
"""
|
"""
|
||||||
token_to_use, user_uu_id_to_use = token or "*", user_uu_id or "*"
|
token_to_use, user_uu_id_to_use = token or "*", user_uu_id or "*"
|
||||||
list_of_token_dict, auth_key_list = [], [cls.AUTH_TOKEN, token_to_use, user_uu_id_to_use]
|
list_of_token_dict, auth_key_list = [], [cls.AUTH_TOKEN, token_to_use, user_uu_id_to_use]
|
||||||
|
print("auth_key_list", auth_key_list)
|
||||||
if token:
|
if token:
|
||||||
result = RedisActions.get_json(list_keys=auth_key_list, limit=1)
|
result = RedisActions.get_json(list_keys=auth_key_list, limit=1)
|
||||||
if first_record := result.first:
|
if first_record := result.first:
|
||||||
|
|
@ -56,7 +57,8 @@ class TokenProvider:
|
||||||
Retrieve token object from Redis using token and user_uu_id
|
Retrieve token object from Redis using token and user_uu_id
|
||||||
"""
|
"""
|
||||||
token_to_use, user_uu_id_to_use = token or "*", user_uu_id or "*"
|
token_to_use, user_uu_id_to_use = token or "*", user_uu_id or "*"
|
||||||
list_of_token_dict, auth_key_list = [], [cls.AUTH_TOKEN, token_to_use, user_uu_id_to_use, "*"]
|
list_of_token_dict, auth_key_list = [], [cls.AUTH_TOKEN, token_to_use, user_uu_id_to_use]
|
||||||
|
print("auth_key_list", auth_key_list)
|
||||||
if token:
|
if token:
|
||||||
result = RedisActions.get_json(list_keys=auth_key_list, limit=1)
|
result = RedisActions.get_json(list_keys=auth_key_list, limit=1)
|
||||||
if first_record := result.first:
|
if first_record := result.first:
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ class RedisHandlers:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_object_from_redis(cls, access_token: str) -> TokenDictType:
|
def get_object_from_redis(cls, access_token: str) -> TokenDictType:
|
||||||
redis_response = RedisActions.get_json(list_keys=[cls.AUTH_TOKEN, access_token, "*", "*"])
|
redis_response = RedisActions.get_json(list_keys=[cls.AUTH_TOKEN, access_token, "*"])
|
||||||
if not redis_response.status:
|
if not redis_response.status:
|
||||||
raise ValueError("EYS_0001")
|
raise ValueError("EYS_0001")
|
||||||
if redis_object := redis_response.first:
|
if redis_object := redis_response.first:
|
||||||
|
|
@ -41,30 +41,27 @@ class RedisHandlers:
|
||||||
raise ValueError("EYS_0002")
|
raise ValueError("EYS_0002")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_object_to_redis(cls, user: Users, token, header_info, add_uuid: str):
|
def set_object_to_redis(cls, user: Users, token, header_info):
|
||||||
result_delete = RedisActions.delete(list_keys=[cls.AUTH_TOKEN, "*", str(user.uu_id), add_uuid])
|
result_delete = RedisActions.delete(list_keys=[cls.AUTH_TOKEN, "*", str(user.uu_id)])
|
||||||
generated_access_token = PasswordModule.generate_access_token()
|
generated_access_token = PasswordModule.generate_access_token()
|
||||||
keys = [cls.AUTH_TOKEN, generated_access_token, str(user.uu_id)]
|
keys = [cls.AUTH_TOKEN, generated_access_token, str(user.uu_id)]
|
||||||
if add_uuid:
|
|
||||||
keys.append(add_uuid)
|
|
||||||
RedisActions.set_json(list_keys=keys, value={**token, **header_info}, expires={"hours": 1, "minutes": 30})
|
|
||||||
return generated_access_token
|
|
||||||
RedisActions.set_json(list_keys=keys, value={**token, **header_info}, expires={"hours": 1, "minutes": 30})
|
RedisActions.set_json(list_keys=keys, value={**token, **header_info}, expires={"hours": 1, "minutes": 30})
|
||||||
return generated_access_token
|
return generated_access_token
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def update_token_at_redis(cls, token: str, add_payload: Union[CompanyToken, OccupantToken], add_uuid: str):
|
def update_token_at_redis(cls, token: str, add_payload: Union[dict], user_uuid: str):
|
||||||
if already_token_data := RedisActions.get_json(list_keys=[cls.AUTH_TOKEN, token, '*', add_uuid]).first:
|
list_keys = [cls.AUTH_TOKEN, token, "*"]
|
||||||
|
print("user_uuid", user_uuid, "add_payload", add_payload)
|
||||||
|
if not user_uuid:
|
||||||
|
raise ValueError("User UUID not found")
|
||||||
|
if already_token_data := RedisActions.get_json(list_keys=list_keys).first:
|
||||||
already_token = cls.process_redis_object(already_token_data)
|
already_token = cls.process_redis_object(already_token_data)
|
||||||
if already_token.is_employee and isinstance(add_payload, CompanyToken):
|
if already_token.is_employee:
|
||||||
already_token.selected_company = add_payload
|
already_token.selected_company = add_payload
|
||||||
list_keys = [cls.AUTH_TOKEN, token, str(already_token.user_uu_id), str(add_uuid)]
|
elif already_token.is_occupant:
|
||||||
print('is_employee: ', list_keys)
|
|
||||||
elif already_token.is_occupant and isinstance(add_payload, OccupantToken):
|
|
||||||
already_token.selected_occupant = add_payload
|
already_token.selected_occupant = add_payload
|
||||||
list_keys = [cls.AUTH_TOKEN, token, str(already_token.user_uu_id), str(add_uuid)]
|
list_keys = [cls.AUTH_TOKEN, token, str(user_uuid)]
|
||||||
print('is_occupant: ', list_keys)
|
print("already_token", already_token)
|
||||||
result = RedisActions.set_json(list_keys=list_keys, value=already_token.model_dump(), expires={"hours": 1, "minutes": 30})
|
result = RedisActions.set_json(list_keys=list_keys, value=already_token.model_dump(), expires={"hours": 1, "minutes": 30})
|
||||||
RedisActions.delete(list_keys=[cls.AUTH_TOKEN, token, str(already_token.user_uu_id)])
|
|
||||||
return result.first
|
return result.first
|
||||||
raise ValueError("Something went wrong")
|
raise ValueError("Something went wrong")
|
||||||
|
|
|
||||||
|
|
@ -238,9 +238,14 @@ class Build(CrudCollection):
|
||||||
building_types = None
|
building_types = None
|
||||||
for part in self.parts:
|
for part in self.parts:
|
||||||
building_types = {}
|
building_types = {}
|
||||||
build_type = BuildTypes.filter_by_one(
|
build_type = BuildTypes.query.filter(
|
||||||
system=True, id=part.build_part_type_id, db=db_session
|
BuildTypes.id == part.build_part_type_id
|
||||||
).data
|
).first()
|
||||||
|
if not build_type:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="There is no building type in this building.",
|
||||||
|
)
|
||||||
if build_type.type_code in building_types:
|
if build_type.type_code in building_types:
|
||||||
building_types[build_type.type_code]["list"].append(part.part_no)
|
building_types[build_type.type_code]["list"].append(part.part_no)
|
||||||
else:
|
else:
|
||||||
|
|
@ -327,9 +332,10 @@ class BuildParts(CrudCollection):
|
||||||
)
|
)
|
||||||
|
|
||||||
def part_name(self, db):
|
def part_name(self, db):
|
||||||
if build_type := BuildTypes.filter_by_one(
|
BuildTypes.set_session(db)
|
||||||
system=True, id=self.part_type_id, db=db
|
if build_type := BuildTypes.query.filter(
|
||||||
).data:
|
BuildTypes.id == self.part_type_id
|
||||||
|
).first():
|
||||||
return f"{str(build_type.type_name).upper()} : {str(self.part_no).upper()}"
|
return f"{str(build_type.type_name).upper()} : {str(self.part_no).upper()}"
|
||||||
return f"Undefined:{str(build_type.type_name).upper()}"
|
return f"Undefined:{str(build_type.type_name).upper()}"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -415,7 +415,8 @@ class Application2Employee(CrudCollection):
|
||||||
applications = Applications.query.filter(Applications.id.in_([application.application_id for application in active_applications])).all()
|
applications = Applications.query.filter(Applications.id.in_([application.application_id for application in active_applications])).all()
|
||||||
if extra_applications := Application2EmployeeExtra.query.filter(Application2EmployeeExtra.employee_id == employee_id).all():
|
if extra_applications := Application2EmployeeExtra.query.filter(Application2EmployeeExtra.employee_id == employee_id).all():
|
||||||
applications_extra = Applications.query.filter(Applications.id.in_([application.application_id for application in extra_applications])).all()
|
applications_extra = Applications.query.filter(Applications.id.in_([application.application_id for application in extra_applications])).all()
|
||||||
applications.extend(applications_extra)
|
if applications_extra:
|
||||||
|
applications.extend(applications_extra)
|
||||||
applications_dict = {}
|
applications_dict = {}
|
||||||
for application in applications:
|
for application in applications:
|
||||||
if not application.site_url in applications_dict:
|
if not application.site_url in applications_dict:
|
||||||
|
|
@ -466,13 +467,6 @@ class Application2Occupant(CrudCollection):
|
||||||
applications_extra = Applications.query.filter(Applications.id.in_([application.application_id for application in extra_applications])).all()
|
applications_extra = Applications.query.filter(Applications.id.in_([application.application_id for application in extra_applications])).all()
|
||||||
applications.extend(applications_extra)
|
applications.extend(applications_extra)
|
||||||
applications_dict = {}
|
applications_dict = {}
|
||||||
for application in applications:
|
|
||||||
if not application.site_url in applications_dict:
|
|
||||||
applications_dict[str(application.site_url)] = str(application.application_code)
|
|
||||||
else:
|
|
||||||
ValueError("Duplicate application code found for single endpoint")
|
|
||||||
applications.extend(applications_extra)
|
|
||||||
applications_dict = {}
|
|
||||||
for application in applications:
|
for application in applications:
|
||||||
if not application.site_url in applications_dict:
|
if not application.site_url in applications_dict:
|
||||||
applications_dict[str(application.site_url)] = str(application.application_code)
|
applications_dict[str(application.site_url)] = str(application.application_code)
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ class OccupantTokenObject(ApplicationToken):
|
||||||
# Occupant Token Object -> Requires selection of the occupant type for a specific build part
|
# Occupant Token Object -> Requires selection of the occupant type for a specific build part
|
||||||
|
|
||||||
available_occupants: dict = None
|
available_occupants: dict = None
|
||||||
selected_occupant: Optional[OccupantToken] = None # Selected Occupant Type
|
selected_occupant: Optional[dict] = None # Selected Occupant Type
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_employee(self) -> bool:
|
def is_employee(self) -> bool:
|
||||||
|
|
@ -109,7 +109,7 @@ class EmployeeTokenObject(ApplicationToken):
|
||||||
duty_id_list: list[int] # List of duty objects
|
duty_id_list: list[int] # List of duty objects
|
||||||
duty_uu_id_list: list[str] # List of duty objects
|
duty_uu_id_list: list[str] # List of duty objects
|
||||||
|
|
||||||
selected_company: Optional[CompanyToken] = None # Selected Company Object
|
selected_company: Optional[dict] = None # Selected Company Object
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_employee(self) -> bool:
|
def is_employee(self) -> bool:
|
||||||
|
|
|
||||||
|
|
@ -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
|
Bina Avukatı Bina Avukatı BU-ATT Bina BU
|
||||||
npm run dev
|
Bina Avukatı Yardımcısı Bina Avukatı Yardımcısı BU-ATA Bina BU
|
||||||
# or
|
Bina Denetmen Yardımcısı Bina Denetmen Yardımcısı BU-SPA Bina BU
|
||||||
yarn dev
|
Bina Denetmeni Bina Denetmeni BU-SPV Bina BU
|
||||||
# or
|
Bina Yönetici Yardımcısı Bina Yönetici Yardımcısı BU-MNA Bina BU
|
||||||
pnpm dev
|
Bina Yöneticisi Bina Yöneticisi BU-MNG Bina BU
|
||||||
# or
|
Bina Muhasabecisi Bina Muhasabecisi BU-ACC Bina BU
|
||||||
bun dev
|
|
||||||
```
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {
|
import {
|
||||||
getSelectionFromRedis,
|
getSelectionFromRedis,
|
||||||
setSelectionToRedis,
|
setActiveSelectionToRedis,
|
||||||
} from "@/fetchers/custom/context/dash/selection/fetch";
|
} from "@/fetchers/custom/context/dash/selection/fetch";
|
||||||
import { AuthError } from "@/fetchers/types/context";
|
import { AuthError } from "@/fetchers/types/context";
|
||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
|
|
@ -43,7 +43,8 @@ export async function GET() {
|
||||||
export async function POST(request: Request) {
|
export async function POST(request: Request) {
|
||||||
try {
|
try {
|
||||||
const selection = await request.json();
|
const selection = await request.json();
|
||||||
await setSelectionToRedis(selection);
|
await setActiveSelectionToRedis(selection);
|
||||||
|
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
status: 200,
|
status: 200,
|
||||||
data: selection || null,
|
data: selection || null,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { NextResponse } from "next/server";
|
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";
|
import { loginSchemaEmail } from "@/pages/single/auth/login/schemas";
|
||||||
|
|
||||||
export async function POST(req: Request): Promise<NextResponse> {
|
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);
|
const userLogin = await loginViaAccessKeys(dataValidated);
|
||||||
|
await initFirstSelection(userLogin.data?.firstSelection, userLogin.data?.userType);
|
||||||
if (userLogin.status === 200 || userLogin.status === 202) {
|
if (userLogin.status === 200 || userLogin.status === 202) {
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
status: 200,
|
status: 200,
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
import { FC, useState, useEffect } from "react";
|
import { FC, useState, useEffect } from "react";
|
||||||
import { HeaderProps } from "@/validations/mutual/dashboard/props";
|
import { HeaderProps } from "@/validations/mutual/dashboard/props";
|
||||||
import { langGetKey } from "@/lib/langGet";
|
import { langGetKey } from "@/lib/langGet";
|
||||||
import { LanguageTypes } from "@/validations/mutual/language/validations";
|
import { LanguageTypes } from "@/validations/mutual/language/validations";
|
||||||
import LanguageSelectionComponent from "@/components/mutual/languageSelection/component";
|
import LanguageSelectionComponent from "@/components/mutual/languageSelection/component";
|
||||||
|
import { apiGetFetcher } from "@/lib/fetcher";
|
||||||
|
|
||||||
const translations = {
|
const translations = {
|
||||||
en: {
|
en: {
|
||||||
|
|
@ -34,30 +36,25 @@ const HeaderComponent: FC<HeaderProps> = ({
|
||||||
userData, userLoading, userError, refreshUser, updateUser
|
userData, userLoading, userError, refreshUser, updateUser
|
||||||
}) => {
|
}) => {
|
||||||
const lang = onlineData?.lang as LanguageTypes || 'en';
|
const lang = onlineData?.lang as LanguageTypes || 'en';
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
const [activeTab, setActiveTab] = useState('notifications');
|
const [activeTab, setActiveTab] = useState('notifications');
|
||||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleFullscreenChange = () => {
|
const handleFullscreenChange = () => { setIsFullscreen(!!document.fullscreenElement) };
|
||||||
setIsFullscreen(!!document.fullscreenElement);
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener('fullscreenchange', handleFullscreenChange);
|
document.addEventListener('fullscreenchange', handleFullscreenChange);
|
||||||
return () => {
|
return () => { document.removeEventListener('fullscreenchange', handleFullscreenChange) };
|
||||||
document.removeEventListener('fullscreenchange', handleFullscreenChange);
|
|
||||||
};
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const toggleFullscreen = () => {
|
const toggleFullscreen = () => {
|
||||||
if (document.fullscreenElement) {
|
if (document.fullscreenElement) { document.exitFullscreen() } else {
|
||||||
document.exitFullscreen();
|
document.documentElement.requestFullscreen().catch(err => { console.error(`Error attempting to enable fullscreen: ${err.message}`) });
|
||||||
} 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 (
|
return (
|
||||||
<div className="py-2 px-6 bg-[#f8f4f3] flex items-center shadow-md shadow-black/5 sticky top-0 left-0 z-30">
|
<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">
|
<button type="button" className="text-lg text-gray-900 font-semibold sidebar-toggle">
|
||||||
|
|
@ -187,10 +184,7 @@ const HeaderComponent: FC<HeaderProps> = ({
|
||||||
<a
|
<a
|
||||||
role="menuitem"
|
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"
|
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) => {
|
onClick={logoutSession}
|
||||||
e.preventDefault();
|
|
||||||
// Handle logout logic here
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{langGetKey(translations[lang], 'logout')}
|
{langGetKey(translations[lang], 'logout')}
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,78 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { FC, useState } from "react";
|
import { FC, useState } from "react";
|
||||||
import renderOneClientSelection from "./renderOneClientSelection";
|
import renderOneClientSelection from "./renderOneClientSelection";
|
||||||
|
|
||||||
interface ClientSelectionSectionProps {
|
interface ClientSelectionSectionProps {
|
||||||
selectionData: any;
|
selectionData: any;
|
||||||
initialSelectedClient?: any;
|
refreshSelection: () => Promise<void>;
|
||||||
onClientSelect?: (client: any) => void;
|
updateSelection: (newSelection: any) => Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ClientSelectionSection: FC<ClientSelectionSectionProps> = ({
|
const ClientSelectionSection: FC<ClientSelectionSectionProps> = ({ selectionData, refreshSelection, updateSelection }) => {
|
||||||
selectionData,
|
const [expandedBuilds, setExpandedBuilds] = useState<{ [key: string]: boolean }>({});
|
||||||
initialSelectedClient = null,
|
|
||||||
onClientSelect
|
if (!selectionData || !selectionData.selectionList) { return null }
|
||||||
}) => {
|
const toggleBuildExpansion = (buildUuid: string) => { setExpandedBuilds(prev => ({ ...prev, [buildUuid]: !prev[buildUuid] })); };
|
||||||
const [selectedClient, setSelectedClient] = useState<any>(initialSelectedClient);
|
const isArray = Array.isArray(selectionData.selectionList);
|
||||||
if (!selectionData || !selectionData.selectionList || selectionData.selectionList.length === 0) { return null }
|
|
||||||
const handleClientSelection = (client: any) => { setSelectedClient(client); if (onClientSelect) { onClientSelect(client) } };
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
{selectionData.selectionList.map((client: any, index: number) => {
|
{isArray ? (
|
||||||
return (
|
selectionData.selectionList.map((client: any, index: number) => {
|
||||||
<div
|
return (
|
||||||
key={client.uu_id || client.id || `client-${index}`}
|
<div key={client.uu_id || client.id || `client-${index}`}>
|
||||||
onClick={() => handleClientSelection(client)}
|
{client && renderOneClientSelection({ item: client, selectedItem: selectionData.activeSelection, updateSelection, refreshSelection })}
|
||||||
>
|
</div>
|
||||||
{client && renderOneClientSelection({
|
);
|
||||||
item: client,
|
})
|
||||||
isSelected: selectedClient?.uu_id === client.uu_id,
|
) : (
|
||||||
onClickHandler: handleClientSelection
|
Object.entries(selectionData.selectionList).map(([buildUuid, buildData]: [string, any]) => {
|
||||||
})}
|
const isExpanded = expandedBuilds[buildUuid] || false;
|
||||||
</div>
|
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>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -13,26 +13,26 @@ import LoadingContent from "@/components/mutual/loader/component";
|
||||||
|
|
||||||
const MenuComponent: FC<MenuProps> = ({
|
const MenuComponent: FC<MenuProps> = ({
|
||||||
activePageUrl, availableApplications, prefix,
|
activePageUrl, availableApplications, prefix,
|
||||||
onlineData, onlineLoading, onlineError,
|
onlineData, onlineLoading, onlineError, refreshOnline, updateOnline,
|
||||||
userData, userLoading, userError,
|
userData, userLoading, userError, refreshUser, updateUser,
|
||||||
selectionData, selectionLoading, selectionError,
|
selectionData, selectionLoading, selectionError, refreshSelection, updateSelection,
|
||||||
menuData, menuLoading, menuError
|
menuData, menuLoading, menuError, refreshMenu, updateMenu
|
||||||
}) => {
|
}) => {
|
||||||
if (menuLoading) { return <MenuLoadingState /> }
|
if (menuLoading) { return <MenuLoadingState /> }
|
||||||
if (menuError) { return <MenuErrorState error={menuError} />; }
|
if (menuError) { return <MenuErrorState error={menuError} />; }
|
||||||
if (availableApplications.length === 0) { return <MenuEmptyState />; }
|
if (availableApplications.length === 0) { return <MenuEmptyState />; }
|
||||||
function handleClientSelection(client: any) { console.log('Client selected:', client) }
|
|
||||||
const lang = onlineData?.lang as LanguageTypes || 'en';
|
const lang = onlineData?.lang as LanguageTypes || 'en';
|
||||||
return (
|
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="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">
|
<div className="flex flex-col">
|
||||||
{/* User Profile Section */}
|
{/* User Profile Section */}
|
||||||
<Suspense fallback={<div><LoadingContent height="h-16" size="w-36 h-48" key={"loading-content"} plane="h-full w-full" /></div>}>
|
<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>
|
</Suspense>
|
||||||
{/* Client Selection Section */}
|
{/* Client Selection Section */}
|
||||||
<Suspense fallback={<div><LoadingContent height="h-16" size="w-36 h-48" key={"loading-content"} plane="h-full w-full" /></div>}>
|
<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>
|
</Suspense>
|
||||||
{/* Menu Items Section */}
|
{/* Menu Items Section */}
|
||||||
<Suspense fallback={<div><LoadingContent height="h-16" size="w-36 h-48" key={"loading-content"} plane="h-full w-full" /></div>}>
|
<Suspense fallback={<div><LoadingContent height="h-16" size="w-36 h-48" key={"loading-content"} plane="h-full w-full" /></div>}>
|
||||||
|
|
|
||||||
|
|
@ -2,32 +2,44 @@
|
||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { Briefcase } from "lucide-react";
|
import { Briefcase } from "lucide-react";
|
||||||
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
item: any;
|
item: any;
|
||||||
isSelected: boolean;
|
selectedItem: any;
|
||||||
onClickHandler: (item: any) => void;
|
refreshSelection: () => Promise<void>;
|
||||||
|
updateSelection: (newSelection: any) => Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RenderOneClientSelection: FC<Props> = ({ item, isSelected, onClickHandler }) => {
|
const selectFromSelectionList = (item: any, selectedItem: any, updateSelection: (newSelection: any) => Promise<boolean>, refreshSelection: () => Promise<void>) => {
|
||||||
if (isSelected) {
|
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 (
|
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">
|
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="flex items-center">
|
||||||
<div className="mr-2 relative">
|
<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">
|
<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="Company" className="w-full h-full object-cover" />) :
|
{item.avatar ? (<img src={item.avatar} alt="Occupant" 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="text-white text-xs font-bold">{getInitials()}</div>)}
|
||||||
</div>
|
</div>
|
||||||
<div className="absolute -bottom-0.5 -right-0.5 bg-white p-0.5 rounded-full border border-amber-400">
|
<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-600" />
|
<Briefcase size={8} className="text-amber-800" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="overflow-hidden">
|
<div className="overflow-hidden">
|
||||||
<h2 className="text-xs font-bold text-black truncate">{item.public_name} {item.company_type}</h2>
|
<h2 className="text-xs font-bold text-white truncate">{getDisplayName()} {item.company_type || ''}</h2>
|
||||||
<p className="text-xs text-amber-800 truncate">{item.duty}</p>
|
<p className="text-xs text-amber-200 truncate">{getDescription()}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -35,21 +47,21 @@ const RenderOneClientSelection: FC<Props> = ({ item, isSelected, onClickHandler
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return (
|
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 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-gray-100 p-2">
|
<div className="bg-amber-300 p-2">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="mr-2 relative">
|
<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">
|
<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="Company" className="w-full h-full object-cover" />) :
|
{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">{(item.duty || "No Duty").slice(0, 2)}</div>)}
|
(<div className="text-white text-xs font-bold">{getInitials()}</div>)}
|
||||||
</div>
|
</div>
|
||||||
<div className="absolute -bottom-0.5 -right-0.5 bg-white p-0.5 rounded-full border border-gray-300">
|
<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-600" />
|
<Briefcase size={8} className="text-gray-500" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="overflow-hidden">
|
<div className="overflow-hidden">
|
||||||
<h2 className="text-xs font-bold text-gray-700 truncate">{item.public_name} {item.company_type}</h2>
|
<h2 className="text-xs font-bold text-gray-600 truncate">{getDisplayName()} {item.company_type || ''}</h2>
|
||||||
<p className="text-xs text-gray-600 truncate">{item.duty}</p>
|
<p className="text-xs text-gray-500 truncate">{getDescription()}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,29 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { ClientUser } from "@/types/mutual/context/validations";
|
import { ClientUser } from "@/types/mutual/context";
|
||||||
import { ClientOnline } from "@/types/mutual/context/validations";
|
import { ClientOnline } from "@/types/mutual/context";
|
||||||
|
import { ClientSelection } from "@/types/mutual/context";
|
||||||
|
|
||||||
interface UserProfileSectionProps {
|
interface UserProfileSectionProps {
|
||||||
userData: ClientUser | null;
|
userData: ClientUser | null;
|
||||||
onlineData: ClientOnline | 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;
|
if (!userData) return null;
|
||||||
return (
|
return (
|
||||||
<div className="mb-2">
|
<div className="mb-2">
|
||||||
|
|
@ -26,7 +40,8 @@ const UserProfileSection: FC<UserProfileSectionProps> = ({ userData, onlineData
|
||||||
<div className="overflow-hidden">
|
<div className="overflow-hidden">
|
||||||
<h2 className="text-sm font-bold text-black truncate">{userData?.person ? `${userData.person.firstname} ${userData.person.surname}` : 'User'}</h2>
|
<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 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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { redis } from "@/lib/redis";
|
||||||
import { functionRetrieveUserSelection } from "@/fetchers/fecther";
|
import { functionRetrieveUserSelection } from "@/fetchers/fecther";
|
||||||
import { ClientSelection, AuthError } from "@/fetchers/types/context";
|
import { ClientSelection, AuthError } from "@/fetchers/types/context";
|
||||||
import { getCompleteFromRedis, setCompleteToRedis } from "@/fetchers/custom/context/complete/fetch";
|
import { getCompleteFromRedis, setCompleteToRedis } from "@/fetchers/custom/context/complete/fetch";
|
||||||
|
import { loginSelectEmployee, loginSelectOccupant } from "@/fetchers/custom/login/login";
|
||||||
|
|
||||||
const getSelectionFromRedis = async (): Promise<ClientSelection> => {
|
const getSelectionFromRedis = async (): Promise<ClientSelection> => {
|
||||||
try {
|
try {
|
||||||
|
|
@ -17,7 +18,7 @@ const getSelectionFromRedis = async (): Promise<ClientSelection> => {
|
||||||
} catch (error) { return { selectionList: [], activeSelection: {} } }
|
} catch (error) { return { selectionList: [], activeSelection: {} } }
|
||||||
}
|
}
|
||||||
|
|
||||||
const setSelectionToRedis = async (selectionObject: ClientSelection) => {
|
const setActiveSelectionToRedis = async (selectionObject: any) => {
|
||||||
try {
|
try {
|
||||||
const decrpytUserSelection = await functionRetrieveUserSelection()
|
const decrpytUserSelection = await functionRetrieveUserSelection()
|
||||||
if (!decrpytUserSelection) throw new AuthError("No user selection found");
|
if (!decrpytUserSelection) throw new AuthError("No user selection found");
|
||||||
|
|
@ -30,10 +31,19 @@ const setSelectionToRedis = async (selectionObject: ClientSelection) => {
|
||||||
const oldData = await getCompleteFromRedis();
|
const oldData = await getCompleteFromRedis();
|
||||||
if (!oldData) throw new AuthError("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: {
|
||||||
|
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;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Re-throw AuthError instances, wrap other errors as AuthError
|
|
||||||
if (error instanceof AuthError) {
|
if (error instanceof AuthError) {
|
||||||
throw error;
|
throw error;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -42,4 +52,4 @@ const setSelectionToRedis = async (selectionObject: ClientSelection) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { getSelectionFromRedis, setSelectionToRedis };
|
export { getSelectionFromRedis, setActiveSelectionToRedis };
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import {
|
||||||
import { retrievePageList } from "@/fetchers/mutual/cookies/token";
|
import { retrievePageList } from "@/fetchers/mutual/cookies/token";
|
||||||
import { deleteAllCookies } from "@/fetchers/mutual/cookies/cookie-actions";
|
import { deleteAllCookies } from "@/fetchers/mutual/cookies/cookie-actions";
|
||||||
import { setMenuToRedis } from "@/fetchers/custom/context/page/menu/fetch";
|
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() {
|
async function logoutActiveSession() {
|
||||||
const response = await fetchDataWithToken(urlLogoutEndpoint, {}, "GET", false);
|
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) {
|
async function initRedis(loginRespone: any, firstSelection: any, accessToken: string, redisKey: string) {
|
||||||
let alreadyAtRedis = null
|
let alreadyAtRedis = null
|
||||||
try {
|
console.log("loginRespone", loginRespone)
|
||||||
const redisData = await getCompleteFromRedis();
|
console.log("firstSelection", firstSelection)
|
||||||
alreadyAtRedis = redisData;
|
console.log("accessToken", accessToken)
|
||||||
} catch (error) { }
|
console.log("redisKey", redisKey)
|
||||||
if (!alreadyAtRedis) {
|
if (!alreadyAtRedis) {
|
||||||
const loginObjectToRedis = {
|
if (loginRespone.user_type.toUpperCase() === "EMPLOYEE") {
|
||||||
online: {
|
const loginObjectToRedis = {
|
||||||
...defaultValuesOnline,
|
online: { ...defaultValuesOnline, lastLogin: new Date(), userType: `${loginRespone.user_type}`.toUpperCase(), lang: loginRespone.user.person.country_code.toLowerCase() },
|
||||||
lastLogin: new Date(),
|
pageConfig: defaultValuesPageConfig,
|
||||||
userType: `${loginRespone.user_type}`.toUpperCase(),
|
menu: defaultValuesMenu,
|
||||||
lang: loginRespone.user.person.country_code.toLowerCase(),
|
header: defaultValuesHeader,
|
||||||
},
|
selection: { selectionList: loginRespone.selection_list, activeSelection: firstSelection },
|
||||||
pageConfig: defaultValuesPageConfig,
|
user: loginRespone.user,
|
||||||
menu: defaultValuesMenu,
|
settings: { lastOnline: new Date(), token: accessToken },
|
||||||
header: defaultValuesHeader,
|
chatRoom: [],
|
||||||
selection: { selectionList: loginRespone.selection_list, activeSelection: firstSelection },
|
notifications: [],
|
||||||
user: loginRespone.user,
|
messages: [],
|
||||||
settings: { lastOnline: new Date(), token: accessToken },
|
}
|
||||||
chatRoom: [],
|
await setNewCompleteToRedis(loginObjectToRedis, redisKey);
|
||||||
notifications: [],
|
} else if (loginRespone.user_type.toUpperCase() === "OCCUPANT") {
|
||||||
messages: [],
|
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) {
|
if (response.status === 200 || response.status === 202) {
|
||||||
|
|
||||||
const loginRespone: any = response?.data;
|
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 nextCrypto = new NextCrypto(tokenSecret);
|
||||||
const accessToken = await nextCrypto.encrypt(loginRespone.access_token);
|
const accessToken = await nextCrypto.encrypt(loginRespone.access_token);
|
||||||
|
const userType = loginRespone.user_type.toUpperCase()
|
||||||
const redisKey = `CLIENT:${loginRespone.user_type.toUpperCase()}:${firstSelection.uu_id}`;
|
const redisKey = `CLIENT:${userType}:${loginRespone.user.uuid}`;
|
||||||
const redisKeyAccess = await nextCrypto.encrypt(redisKey);
|
const redisKeyAccess = await nextCrypto.encrypt(redisKey);
|
||||||
const usersSelection = await nextCrypto.encrypt(
|
const usersSelection = await nextCrypto.encrypt(JSON.stringify({ selected: firstSelection, userType, redisKey }));
|
||||||
JSON.stringify({
|
|
||||||
selected: firstSelection.uu_id,
|
|
||||||
userType: loginRespone.user_type.toUpperCase(),
|
|
||||||
redisKey,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
await initRedis(loginRespone, firstSelection, accessToken, redisKey);
|
await initRedis(loginRespone, firstSelection, accessToken, redisKey);
|
||||||
|
|
||||||
cookieStore.set({
|
cookieStore.set({
|
||||||
name: "eys-zzz",
|
name: "eys-zzz",
|
||||||
value: accessToken,
|
value: accessToken,
|
||||||
|
|
@ -99,12 +122,16 @@ async function loginViaAccessKeys(payload: LoginViaAccessKeys) {
|
||||||
value: usersSelection,
|
value: usersSelection,
|
||||||
...cookieObject,
|
...cookieObject,
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return {
|
return {
|
||||||
completed: true,
|
completed: true,
|
||||||
message: "Login successful",
|
message: "Login successful",
|
||||||
status: 200,
|
status: 200,
|
||||||
data: loginRespone,
|
data: {
|
||||||
|
userType,
|
||||||
|
firstSelection,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("JSON parse error:", error);
|
console.error("JSON parse error:", error);
|
||||||
|
|
@ -112,7 +139,10 @@ async function loginViaAccessKeys(payload: LoginViaAccessKeys) {
|
||||||
completed: false,
|
completed: false,
|
||||||
message: "Login NOT successful",
|
message: "Login NOT successful",
|
||||||
status: 401,
|
status: 401,
|
||||||
data: "{}",
|
data: {
|
||||||
|
userType,
|
||||||
|
firstSelection,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -135,65 +165,32 @@ async function loginViaAccessKeys(payload: LoginViaAccessKeys) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loginSelectEmployee(payload: LoginSelect) {
|
async function loginSelectEmployee(payload: LoginSelect) {
|
||||||
const cookieStore = await cookies();
|
|
||||||
const nextCrypto = new NextCrypto(tokenSecret);
|
|
||||||
const employeeUUID = payload.uuid;
|
const employeeUUID = payload.uuid;
|
||||||
const redisKey = `CLIENT:EMPLOYEE:${employeeUUID}`;
|
|
||||||
const selectResponse: any = await fetchDataWithToken(urlLoginSelectEndpoint, { uuid: employeeUUID }, "POST", false);
|
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) {
|
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 {
|
try {
|
||||||
const pageList = await retrievePageList()
|
console.log("selectResponse", selectResponse)
|
||||||
await setMenuToRedis({
|
|
||||||
selectionList: pageList,
|
|
||||||
activeSelection: "/dashboard"
|
|
||||||
})
|
|
||||||
} catch (error) { }
|
} catch (error) { }
|
||||||
}
|
}
|
||||||
return selectResponse;
|
return selectResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loginSelectOccupant(payload: LoginSelectOccupant) {
|
async function loginSelectOccupant(payload: LoginSelect) {
|
||||||
const livingSpaceUUID = payload.uuid;
|
const livingSpaceUUID = payload.uuid;
|
||||||
const cookieStore = await cookies();
|
|
||||||
const nextCrypto = new NextCrypto(tokenSecret);
|
|
||||||
|
|
||||||
const selectResponse: any = await fetchDataWithToken(urlLoginSelectEndpoint, { uuid: livingSpaceUUID }, "POST", false);
|
const selectResponse: any = await fetchDataWithToken(urlLoginSelectEndpoint, { uuid: livingSpaceUUID }, "POST", false);
|
||||||
const redisKey = `CLIENT:OCCUPANT:${livingSpaceUUID}`;
|
console.log("selectResponse", selectResponse)
|
||||||
cookieStore.delete("eys-sel");
|
|
||||||
|
|
||||||
if (selectResponse.status === 200 || selectResponse.status === 202) {
|
if (selectResponse.status === 200 || selectResponse.status === 202) {
|
||||||
const usersSelection = await nextCrypto.encrypt(
|
try {
|
||||||
JSON.stringify({
|
console.log("selectResponse", selectResponse)
|
||||||
selected: livingSpaceUUID,
|
} catch (error) { }
|
||||||
userType: "OCCUPANT",
|
|
||||||
redisKey,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
cookieStore.set({
|
|
||||||
name: "eys-sel",
|
|
||||||
value: usersSelection,
|
|
||||||
...cookieObject,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return selectResponse;
|
return selectResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
loginViaAccessKeys,
|
loginViaAccessKeys,
|
||||||
|
initFirstSelection,
|
||||||
loginSelectEmployee,
|
loginSelectEmployee,
|
||||||
loginSelectOccupant,
|
loginSelectOccupant,
|
||||||
logoutActiveSession,
|
logoutActiveSession,
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,4 @@ interface LoginSelect {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LoginSelectOccupant {
|
export type { LoginViaAccessKeys, LoginSelect };
|
||||||
uuid: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type { LoginViaAccessKeys, LoginSelect, LoginSelectOccupant };
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
import { DashboardPage } from "@/components/custom/content/DashboardPage";
|
import { DashboardPage } from "@/components/custom/content/DashboardPage";
|
||||||
|
|
||||||
const pageIndexMulti: Record<string, Record<string, React.FC<any>>> = {
|
const pageIndexMulti: Record<string, Record<string, React.FC<any>>> = {
|
||||||
"/dashboard": {
|
"/dashboard": { DashboardPage: DashboardPage },
|
||||||
DashboardPage: DashboardPage,
|
|
||||||
},
|
|
||||||
// Add more pages as needed
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export { pageIndexMulti };
|
export { pageIndexMulti };
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue