From 69e6e659e03d9d0cdb9b62302e0df3c4cf9f3d46 Mon Sep 17 00:00:00 2001 From: Horacio Daniel Ros Date: Mon, 14 Sep 2026 14:26:38 -0300 Subject: [PATCH] =?UTF-8?q?feat:=20unificar=20l=C3=B3gica=20de=20verificac?= =?UTF-8?q?i=C3=B3n=20de=20administrador=20y=20gesti=C3=B3n=20del=20bot?= =?UTF-8?q?=C3=B3n=20de=20edici=C3=B3n=20en=20OrganizationPublicProfile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/api/Companies/Companies.Controller.ts | 38 +++--- txclient/src/app/landing/org/[oid]/page.tsx | 114 ++++++++++-------- 2 files changed, 86 insertions(+), 66 deletions(-) diff --git a/server/src/api/Companies/Companies.Controller.ts b/server/src/api/Companies/Companies.Controller.ts index 69365d1..a693930 100644 --- a/server/src/api/Companies/Companies.Controller.ts +++ b/server/src/api/Companies/Companies.Controller.ts @@ -38,7 +38,7 @@ export class ToggleCompanyFixedPostController extends Controller { @SuccessResponse(200, "Done") @Post() public async toggleFixedCompanyPost( - @Body() requestBody: FixCompanyPostParams + @Body() requestBody: FixCompanyPostParams, ): Promise { try { await new CompaniesService().toggleFixedPost(requestBody); @@ -62,7 +62,7 @@ export class MoveCompanyFixedPostController extends Controller { @SuccessResponse(200, "Done") @Post() public async moveFixedCompanyPost( - @Body() requestBody: MoveCompanyFixedPostParams + @Body() requestBody: MoveCompanyFixedPostParams, ): Promise { try { await new CompaniesService().moveFixedPost(requestBody); @@ -86,7 +86,7 @@ export class SetNotificationsStatusCompanyController extends Controller { @SuccessResponse(200, "Done") @Post() public async setNotificationAuto( - @Body() requestBody: SetNotificationAutoParams + @Body() requestBody: SetNotificationAutoParams, ): Promise { try { await new CompaniesService().setNotificationAuto(requestBody); @@ -110,7 +110,7 @@ export class SetPublishedStatusCompanyController extends Controller { @SuccessResponse(200, "Done") @Post() public async setPublishedStatus( - @Body() requestBody: SetOrganizationPublishedStatusParams + @Body() requestBody: SetOrganizationPublishedStatusParams, ): Promise { try { await new CompaniesService().setPublishedStatus(requestBody); @@ -134,7 +134,7 @@ export class CreateCompanyController extends Controller { @SuccessResponse(200, "La compañia fue creada con exito") @Post() public async createCompany( - @Body() requestBody: CreateCompanyParams + @Body() requestBody: CreateCompanyParams, ): Promise { try { const company = await new CompaniesService().createCompany(requestBody); @@ -155,7 +155,7 @@ export class DeleteCompanyController extends Controller { @SuccessResponse(200, "La compañia fue modificada con exito") @Post() public async deleteCompany( - @Body() requestBody: DeleteCompanyParams + @Body() requestBody: DeleteCompanyParams, ): Promise { try { await new CompaniesService().deleteCompany(requestBody); @@ -179,7 +179,7 @@ export class UpdateCompanyController extends Controller { @SuccessResponse(200, "La compañia fue modificada con exito") @Post() public async updateCompany( - @Body() requestBody: UpdateCompanyParams + @Body() requestBody: UpdateCompanyParams, ): Promise { try { await new CompaniesService().updateCompany(requestBody); @@ -202,7 +202,7 @@ export class GetCompanyByIdController extends Controller { @SuccessResponse(200, "Done") @Post() public async getById( - @Body() requestBody: OranizationsViewByIdParams + @Body() requestBody: OranizationsViewByIdParams, ): Promise { try { const companies = await new CompaniesService().getById(requestBody); @@ -222,7 +222,7 @@ export class GetCompanyByUserController extends Controller { @SuccessResponse(200, "Done") @Post() public async getByUserId( - @Body() requestBody: MyOranizationsViewParams + @Body() requestBody: MyOranizationsViewParams, ): Promise { try { const companies = await new CompaniesService().getByUserId(requestBody); @@ -242,7 +242,7 @@ export class PaginateCompanyController extends Controller { @SuccessResponse(200, "Done") @Post() public async paginateUsers( - @Body() requestBody: PaginateCompaniesParams + @Body() requestBody: PaginateCompaniesParams, ): Promise { try { const users = await new CompaniesService().paginateCompanies(requestBody); @@ -265,7 +265,7 @@ export class UploadCompanyHeaderController extends Controller { public async uploadHeader( @FormField() companyId: string, @FormField() sessionUser: string, - @UploadedFile() file: Express.Multer.File + @UploadedFile() file: Express.Multer.File, ): Promise { try { await new CompaniesService().setCompanyHeader({ @@ -295,7 +295,7 @@ export class UploadCompanyIconController extends Controller { public async uploadIcon( @FormField() companyId: string, @FormField() sessionUser: string, - @UploadedFile() file: Express.Multer.File + @UploadedFile() file: Express.Multer.File, ): Promise { try { await new CompaniesService().setCompanyIcon({ @@ -325,7 +325,7 @@ export class DeleteCompanyHeaderController extends Controller { @SuccessResponse(200, "El archivo fue cargado con exito") @Post() public async deleteHeader( - @Body() data: DeleteCompanyFileParams + @Body() data: DeleteCompanyFileParams, ): Promise { try { await new CompaniesService().deleteCompanyHeader(data); @@ -349,7 +349,7 @@ export class DeleteCompanyIconController extends Controller { @SuccessResponse(200, "El archivo fue cargado con exito") @Post() public async deleteIcon( - @Body() data: DeleteCompanyFileParams + @Body() data: DeleteCompanyFileParams, ): Promise { try { await new CompaniesService().deleteCompanyIcon(data); @@ -372,7 +372,7 @@ export class filterAllOrganizationsController extends Controller { @SuccessResponse(200, "Done") @Post() public async filterAllOrganizations( - @Body() requestBody: PaginateCompaniesParams + @Body() requestBody: PaginateCompaniesParams, ): Promise { try { const clients = await new CompaniesService().filterAll(requestBody); @@ -392,7 +392,7 @@ export class CheckCompanyNameController extends Controller { @SuccessResponse(200, "Done") @Post() public async checkName( - @Body() requestBody: { name: string } + @Body() requestBody: { name: string }, ): Promise<{ valid: boolean } | ApiValidationError> { try { const valid = await new CompaniesService().checkNameExists(requestBody.name); @@ -413,12 +413,12 @@ export class CheckCompanyAdminController extends Controller { @SuccessResponse(200, "Done") @Post() public async checkAdmin( - @Body() requestBody: { companyId: string; sessionUser: string } - ): Promise<{ isAdmin: boolean } | ApiValidationError> { + @Body() requestBody: { companyId: string; sessionUser: string }, + ): Promise { try { const isAdmin = await new CompaniesService().checkCompanyAdmin(requestBody); this.setStatus(200); - return { isAdmin }; + return isAdmin; } catch (e) { const errorOccurred: Error = e as Error; this.setStatus(500); diff --git a/txclient/src/app/landing/org/[oid]/page.tsx b/txclient/src/app/landing/org/[oid]/page.tsx index ffca279..a9f6013 100644 --- a/txclient/src/app/landing/org/[oid]/page.tsx +++ b/txclient/src/app/landing/org/[oid]/page.tsx @@ -104,47 +104,83 @@ export default function OrganizationPublicProfile() { const [currentPage, setCurrentPage] = useState(1); const [isOrgAdmin, setIsOrgAdmin] = useState(false); const [showEditPopup, setShowEditPopup] = useState(false); + const SessionInfo = useSessionStore(); - // Append edit button to header wrapper when admin + // Unified effect: check admin status and manage edit button DOM element useEffect(() => { - if (!isOrgAdmin) return; + if (!SessionInfo.userId || !oid) { + setIsOrgAdmin(false); + const existing = document.getElementById("edit-header-btn"); + if (existing) existing.remove(); + return; + } - const wrapper = document.getElementById("header-wrapper"); - if (!wrapper) return; + let cancelled = false; - const btn = document.createElement("div"); - btn.id = "edit-header-btn"; - btn.innerHTML = ` - - `; - btn.querySelector("button")!.addEventListener("click", () => setShowEditPopup(true)); - wrapper.appendChild(btn); + checkOrgAdmin(oid, SessionInfo.userId) + .then((isAdmin) => { + if (cancelled) return; + console.log("isAdmin:", isAdmin); + setIsOrgAdmin(isAdmin); + // Append or remove button based on the result + const wrapper = document.getElementById("header-wrapper"); + if (!wrapper) return; + + if (isAdmin) { + const existingBtn = document.getElementById("edit-header-btn"); + if (existingBtn) existingBtn.remove(); + + const btn = document.createElement("div"); + btn.id = "edit-header-btn"; + btn.innerHTML = ` + + `; + btn.querySelector("button")!.addEventListener("click", () => + setShowEditPopup(true), + ); + wrapper.appendChild(btn); + } else { + // Remove button for non-admin users + const existingBtn = document.getElementById("edit-header-btn"); + if (existingBtn) existingBtn.remove(); + } + }) + .catch(() => { + if (cancelled) return; + setIsOrgAdmin(false); + + // Ensure button is removed on error + const existingBtn = document.getElementById("edit-header-btn"); + if (existingBtn) existingBtn.remove(); + }); + + // Cleanup: mark as cancelled and remove button return () => { + cancelled = true; const existing = document.getElementById("edit-header-btn"); if (existing) existing.remove(); }; - }, [isOrgAdmin]); + }, [SessionInfo.userId, oid]); - const SessionInfo = useSessionStore(); const eventHandler = useEventHandlerStore(); const alert = useAlert(); const confirm = useConfirmStore(); @@ -186,22 +222,6 @@ export default function OrganizationPublicProfile() { }); }, [SessionInfo, authorizedUsers]); - // Check if the logged-in user is admin of this organization - useEffect(() => { - if (!SessionInfo.userId || !oid) { - setIsOrgAdmin(false); - return; - } - - checkOrgAdmin(oid, SessionInfo.userId) - .then((isAdmin) => { - setIsOrgAdmin(isAdmin); - }) - .catch(() => { - setIsOrgAdmin(false); - }); - }, [SessionInfo.userId, oid]); - useEffect(() => { if (!OrganizationData.orgData) return; if (!oid) return; //if (!OrganizationData.orgData.id) return;