From 6075f1ad107e71b2b17cbf241b68fe371b6e53d6 Mon Sep 17 00:00:00 2001 From: amee Date: Thu, 9 Apr 2026 11:26:50 +0530 Subject: [PATCH] bug list fixes! --- .../admin/components/ModuleEnvironments.tsx | 22 +++- .../modules/admin/components/ModuleList.tsx | 34 +++++- .../modules/admin/hooks/useModuleApi.ts | 2 +- src/application/profile/ProfilePage.tsx | 4 +- src/application/roles/components/AllRoles.tsx | 2 +- .../theme/components/AllPalettes.tsx | 111 +++++++++++------- src/application/users/components/AllUsers.tsx | 7 +- src/components/custom/index.ts | 3 +- src/i18n/locales/ar/theme.json | 6 + src/i18n/locales/en/theme.json | 8 +- 10 files changed, 139 insertions(+), 60 deletions(-) diff --git a/src/application/modules/admin/components/ModuleEnvironments.tsx b/src/application/modules/admin/components/ModuleEnvironments.tsx index e7c733e..1b1fda9 100644 --- a/src/application/modules/admin/components/ModuleEnvironments.tsx +++ b/src/application/modules/admin/components/ModuleEnvironments.tsx @@ -4,6 +4,7 @@ import { ArrowLeft, Plus, Edit, Trash2, Check, X } from 'lucide-react'; import { adminModuleApi } from '../AdminModuleApi'; import type { ModuleEnvironment, Module } from '../AdminModuleTypes'; import EnvironmentForm from './EnvironmentForm'; +import { CustomConfirmationModal } from '../../../../components/custom'; const ModuleEnvironments = () => { const { moduleId } = useParams<{ moduleId: string }>(); @@ -13,6 +14,7 @@ const ModuleEnvironments = () => { const [loading, setLoading] = useState(true); const [showForm, setShowForm] = useState(false); const [selectedEnv, setSelectedEnv] = useState(null); + const [envToDelete, setEnvToDelete] = useState(null); const fetchData = async () => { if (!moduleId) return; @@ -47,14 +49,17 @@ const ModuleEnvironments = () => { }; const handleDelete = async (env: ModuleEnvironment) => { - if (!moduleId) return; - if (!confirm(`Delete environment "${env.slug}"?`)) return; + setEnvToDelete(env); + }; + const confirmDelete = async () => { + if (!moduleId || !envToDelete) return; try { - await adminModuleApi.deleteEnvironment(moduleId, env.id); + await adminModuleApi.deleteEnvironment(moduleId, envToDelete.id); + setEnvToDelete(null); fetchData(); } catch (error: any) { - alert(error.response?.data?.detail || 'Failed to delete environment'); + console.error('Failed to delete environment', error); } }; @@ -168,6 +173,15 @@ const ModuleEnvironments = () => { )} + setEnvToDelete(null)} + onConfirm={confirmDelete} + title="Delete Environment" + description={`Are you sure you want to delete ${envToDelete?.slug} environment?`} + variant="danger" + /> + {showForm && moduleId && ( { const navigate = useNavigate(); const { t } = useTranslation(['modules', 'common']); - const { listModules, deleteModule, loading } = useModuleApi(); + const { listModules, deleteModule, updateModule, loading } = useModuleApi(); const [modules, setModules] = useState([]); const [showForm, setShowForm] = useState(false); const [selectedModule, setSelectedModule] = useState(null); const [moduleToDelete, setModuleToDelete] = useState(null); + const [togglingId, setTogglingId] = useState(null); const fetchModules = async () => { const data = await listModules(); @@ -44,7 +46,6 @@ const ModuleList = () => { const handleDelete = async () => { if (!moduleToDelete) return; - const success = await deleteModule(moduleToDelete.id); if (success) { fetchModules(); @@ -106,11 +107,36 @@ const ModuleList = () => {

{module.module_id}

-
+
{ + if (togglingId) return; + try { + setTogglingId(module.id); + const updated = await adminModuleApi.updateModule(module.id, { + status: module.status === 'active' ? 'inactive' : 'active' + }); + if (updated) { + setModules(prev => prev.map(m => + m.id === module.id ? { ...m, status: updated.status } : m + )); + } + } catch (error) { + console.error("Toggle failed:", error); + } finally { + setTogglingId(null); + } + }} + > {module.status === 'active' ? ( ) : ( - + )}
diff --git a/src/application/modules/admin/hooks/useModuleApi.ts b/src/application/modules/admin/hooks/useModuleApi.ts index 8e680c6..c2aefa5 100644 --- a/src/application/modules/admin/hooks/useModuleApi.ts +++ b/src/application/modules/admin/hooks/useModuleApi.ts @@ -79,7 +79,7 @@ export const useModuleApi = (): UseModuleApiResult => { []); const updateModule = useCallback((id: string, data: ModuleUpdate) => - wrapRequest(() => adminModuleApi.updateModule(id, data), 'update module', 'Module updated successfully'), + wrapRequest(() => adminModuleApi.updateModule(id, data), 'update module'), []); const deleteModule = useCallback(async (id: string) => { diff --git a/src/application/profile/ProfilePage.tsx b/src/application/profile/ProfilePage.tsx index 25b8ac5..d0346ea 100644 --- a/src/application/profile/ProfilePage.tsx +++ b/src/application/profile/ProfilePage.tsx @@ -129,8 +129,8 @@ const ProfilePage: React.FC = () => { return; } - if (passwordForm.newPassword !== passwordForm.confirmPassword) { - setPasswordError(t('messages.passwordMismatch')); + if (passwordForm.newPassword === passwordForm.confirmPassword) { + setPasswordError("New password must be different from your current password"); return; } diff --git a/src/application/roles/components/AllRoles.tsx b/src/application/roles/components/AllRoles.tsx index 43ef86e..e718b6d 100644 --- a/src/application/roles/components/AllRoles.tsx +++ b/src/application/roles/components/AllRoles.tsx @@ -467,7 +467,7 @@ const AllRoles = () => { footer={ <> {t('actions.cancel')} - {t('update')} + {t('actions.update')} } > diff --git a/src/application/theme/components/AllPalettes.tsx b/src/application/theme/components/AllPalettes.tsx index a07bf88..3ccc09f 100644 --- a/src/application/theme/components/AllPalettes.tsx +++ b/src/application/theme/components/AllPalettes.tsx @@ -1,9 +1,8 @@ import React, { useEffect, useState, useMemo } from "react"; import { Plus, Edit2, Trash2 } from "lucide-react"; -import { toast } from "react-toastify"; -import {CustomButton} from "../../../components/custom"; +import { CustomButton } from "../../../components/custom"; import DataTable, { type ColumnDef } from "../../../components/custom/CustomTable"; -import { CustomActionMenu, CustomActionItem, CustomStatus } from "../../../components/custom"; +import { CustomActionMenu, CustomActionItem, CustomStatus, CustomConfirmationModal } from "../../../components/custom"; import { Loader } from "../../../components/custom/CustomLoader"; import { paletteApi } from "../PaletteApi"; import type { ColorPalette } from "../ThemeTypes"; @@ -18,6 +17,8 @@ const AllPalettes: React.FC = () => { const [errorMessage, setErrorMessage] = useState(""); const [isModalOpen, setIsModalOpen] = useState(false); const [editingPalette, setEditingPalette] = useState(null); + const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); + const [deleteId, setDeleteId] = useState(null); const { refreshTheme } = useTheme(); const fetchPalettes = async () => { @@ -49,14 +50,22 @@ const AllPalettes: React.FC = () => { setIsModalOpen(true); }; - const handleDelete = async (id: string) => { - if (!window.confirm(t('theme:confirmDelete'))) return; + const handleDelete = (id: string, isDefault: boolean) => { + if (isDefault) return; + setDeleteId(id); + setIsDeleteModalOpen(true); + }; + + const handleConfirmDelete = async () => { + if (!deleteId) return; try { - await paletteApi.deletePalette(id); - toast.success(t('theme:success.deleted')); + await paletteApi.deletePalette(deleteId); fetchPalettes(); } catch (error) { - // toast handled by api client + console.error("Failed to delete palette", error); + } finally { + setIsDeleteModalOpen(false); + setDeleteId(null); } }; @@ -65,10 +74,8 @@ const AllPalettes: React.FC = () => { try { if (editingPalette) { await paletteApi.updatePalette(editingPalette.id, data); - toast.success(t('theme:success.updated')); } else { await paletteApi.createPalette(data); - toast.success(t('theme:success.created')); } setIsModalOpen(false); fetchPalettes(); @@ -136,7 +143,7 @@ const AllPalettes: React.FC = () => { handleDelete(row.id)} + onClick={() => handleDelete(row.id, row.is_default)} className={`${row.is_default ? "opacity-50 cursor-not-allowed" : "text-red-600 hover:text-red-700 hover:bg-red-50"}`} >
{ ), }, ], - [] + [t] ); return ( -
-
-
-

{t('theme:title')}

- {/*

- Manage system color themes and default palettes. -

*/} + <> +
+
+
+

{t('theme:title')}

+ {/*

+ Manage system color themes and default palettes. +

*/} +
+ }> + {t('theme:actions.create')} +
- }> - {t('theme:actions.create')} - + + {isLoading ? ( +
+ +
+ ) : errorMessage ? ( +
+ {errorMessage} +
+ ) : ( + row.name} + /> + )} + + setIsModalOpen(false)} + isLoading={isLoading} + />
- {isLoading ? ( -
- -
- ) : errorMessage ? ( -
- {errorMessage} -
- ) : ( - - )} - - setIsModalOpen(false)} + setIsDeleteModalOpen(false)} + title={t('theme:deleteModal.title')} + description={t('theme:deleteModal.message')} + confirmText={t('theme:deleteModal.confirm')} + cancelText={t('theme:deleteModal.cancel')} isLoading={isLoading} /> -
+ ); }; diff --git a/src/application/users/components/AllUsers.tsx b/src/application/users/components/AllUsers.tsx index c0e22c0..a14a2b9 100644 --- a/src/application/users/components/AllUsers.tsx +++ b/src/application/users/components/AllUsers.tsx @@ -14,6 +14,7 @@ import { CustomActionMenu, CustomActionItem, CustomStatus, + CustomPhoneInput, } from "../../../components/custom"; import type { ColumnDef } from "../../../components/custom/CustomTable"; import type { @@ -281,6 +282,10 @@ const AllUsers = () => { [] ); + const handleEditPhoneChange = useCallback((val: string | undefined) => { + setEditForm((prev) => ({ ...prev, phone_number: val || "" })); + }, []); + const handleStatusChange = useCallback( (e: React.ChangeEvent) => { setEditForm((prev) => ({ @@ -523,7 +528,7 @@ const AllUsers = () => { - +