diff --git a/worklenz-backend/src/controllers/task-phases-controller.ts b/worklenz-backend/src/controllers/task-phases-controller.ts index e72fbbab..163ff250 100644 --- a/worklenz-backend/src/controllers/task-phases-controller.ts +++ b/worklenz-backend/src/controllers/task-phases-controller.ts @@ -16,19 +16,23 @@ export default class TaskPhasesController extends WorklenzControllerBase { if (!req.query.id) return res.status(400).send(new ServerResponse(false, null, "Invalid request")); + // Use custom name if provided, otherwise use default naming pattern + const phaseName = req.body.name?.trim() || + `Untitled Phase (${(await db.query("SELECT COUNT(*) FROM project_phases WHERE project_id = $1", [req.query.id])).rows[0].count + 1})`; + const q = ` INSERT INTO project_phases (name, color_code, project_id, sort_index) VALUES ( - CONCAT('Untitled Phase (', (SELECT COUNT(*) FROM project_phases WHERE project_id = $2) + 1, ')'), $1, $2, - (SELECT COUNT(*) FROM project_phases WHERE project_id = $2) + 1) + $3, + (SELECT COUNT(*) FROM project_phases WHERE project_id = $3) + 1) RETURNING id, name, color_code, sort_index; `; req.body.color_code = this.DEFAULT_PHASE_COLOR; - const result = await db.query(q, [req.body.color_code, req.query.id]); + const result = await db.query(q, [phaseName, req.body.color_code, req.query.id]); const [data] = result.rows; data.color_code = getColor(data.name) + TASK_STATUS_COLOR_ALPHA; diff --git a/worklenz-frontend/public/locales/alb/phases-drawer.json b/worklenz-frontend/public/locales/alb/phases-drawer.json index 23816727..b0ba817b 100644 --- a/worklenz-frontend/public/locales/alb/phases-drawer.json +++ b/worklenz-frontend/public/locales/alb/phases-drawer.json @@ -1,16 +1,20 @@ { "configurePhases": "Konfiguro Fazat", + "configure": "Konfiguro", "phaseLabel": "Etiketa e Fazës", - "enterPhaseName": "Shkruani emrin e fazës", + "enterPhaseName": "Shkruaj emrin e fazës", "addOption": "Shto Opsion", "phaseOptions": "Opsionet e Fazës", - "dragToReorderPhases": "Zvarrit fazat për t'i rirenditur. Çdo fazë mund të ketë një ngjyrë të ndryshme.", - "enterNewPhaseName": "Shkruani emrin e fazës së re...", + "optionsText": "Opsione", + "dragToReorderPhases": "Tërhiq fazat për t'i rirenditur. Çdo fazë mund të ketë një ngjyrë të ndryshme.", + "enterNewPhaseName": "Shkruaj emrin e fazës së re...", "addPhase": "Shto Fazë", "noPhasesFound": "Nuk u gjetën faza", + "no": "Asnjë", + "found": "u gjet", "deletePhase": "Fshi Fazën", - "deletePhaseConfirm": "Jeni të sigurt që doni të fshini këtë fazë? Ky veprim nuk mund të zhbëhet.", - "rename": "Riemëro", + "deletePhaseConfirm": "Jeni i sigurt që doni të fshini këtë fazë? Ky veprim nuk mund të zhbëhet.", + "rename": "Riemërto", "delete": "Fshi", "create": "Krijo", "cancel": "Anulo", diff --git a/worklenz-frontend/public/locales/alb/task-list-filters.json b/worklenz-frontend/public/locales/alb/task-list-filters.json index e75e4802..4fc4dbdf 100644 --- a/worklenz-frontend/public/locales/alb/task-list-filters.json +++ b/worklenz-frontend/public/locales/alb/task-list-filters.json @@ -68,9 +68,10 @@ "clearing": "Po pastron...", "cancel": "Anulo", "search": "Kërko", - "groupedBy": "I grupuar sipas", - "manageStatuses": "Menaxho statuset", - "managePhases": "Menaxho fazat", + "groupedBy": "Grupuar sipas", + "manage": "Menaxho", + "manageStatuses": "Menaxho Statuset", + "managePhases": "Menaxho Fazat", "dragToReorderStatuses": "Statuset janë të organizuara sipas kategorive. Tërhiq për të rirenditur brenda kategorive. Kliko 'Shto status' për të krijuar statuse të reja në çdo kategori.", "enterNewStatusName": "Shkruani emrin e statusit të ri...", "addStatus": "Shto status", diff --git a/worklenz-frontend/public/locales/de/phases-drawer.json b/worklenz-frontend/public/locales/de/phases-drawer.json index 4a143c7f..3cdfb255 100644 --- a/worklenz-frontend/public/locales/de/phases-drawer.json +++ b/worklenz-frontend/public/locales/de/phases-drawer.json @@ -1,13 +1,17 @@ { "configurePhases": "Phasen konfigurieren", - "phaseLabel": "Phasenbezeichnung", - "enterPhaseName": "Phasennamen eingeben", + "configure": "Konfigurieren", + "phaseLabel": "Phasen-Label", + "enterPhaseName": "Phasenname eingeben", "addOption": "Option hinzufügen", "phaseOptions": "Phasenoptionen", + "optionsText": "Optionen", "dragToReorderPhases": "Ziehen Sie Phasen, um sie neu zu ordnen. Jede Phase kann eine andere Farbe haben.", "enterNewPhaseName": "Neuen Phasennamen eingeben...", "addPhase": "Phase hinzufügen", "noPhasesFound": "Keine Phasen gefunden", + "no": "Keine", + "found": "gefunden", "deletePhase": "Phase löschen", "deletePhaseConfirm": "Sind Sie sicher, dass Sie diese Phase löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.", "rename": "Umbenennen", diff --git a/worklenz-frontend/public/locales/de/task-list-filters.json b/worklenz-frontend/public/locales/de/task-list-filters.json index 743f036a..18d50b6c 100644 --- a/worklenz-frontend/public/locales/de/task-list-filters.json +++ b/worklenz-frontend/public/locales/de/task-list-filters.json @@ -69,6 +69,7 @@ "cancel": "Abbrechen", "search": "Suchen", "groupedBy": "Gruppiert nach", + "manage": "Verwalten", "manageStatuses": "Status verwalten", "managePhases": "Phasen verwalten", "dragToReorderStatuses": "Status sind nach Kategorien organisiert. Ziehen Sie, um innerhalb von Kategorien neu zu ordnen. Klicken Sie auf 'Status hinzufügen', um neue Status in jeder Kategorie zu erstellen.", diff --git a/worklenz-frontend/public/locales/en/phases-drawer.json b/worklenz-frontend/public/locales/en/phases-drawer.json index 7791a08b..9eb24582 100644 --- a/worklenz-frontend/public/locales/en/phases-drawer.json +++ b/worklenz-frontend/public/locales/en/phases-drawer.json @@ -1,13 +1,17 @@ { "configurePhases": "Configure Phases", + "configure": "Configure", "phaseLabel": "Phase Label", "enterPhaseName": "Enter phase name", "addOption": "Add Option", "phaseOptions": "Phase Options", + "optionsText": "Options", "dragToReorderPhases": "Drag phases to reorder them. Each phase can have a different color.", "enterNewPhaseName": "Enter new phase name...", "addPhase": "Add Phase", "noPhasesFound": "No phases found", + "no": "No", + "found": "found", "deletePhase": "Delete Phase", "deletePhaseConfirm": "Are you sure you want to delete this phase? This action cannot be undone.", "rename": "Rename", diff --git a/worklenz-frontend/public/locales/en/task-list-filters.json b/worklenz-frontend/public/locales/en/task-list-filters.json index 36ee10dc..118ac4ce 100644 --- a/worklenz-frontend/public/locales/en/task-list-filters.json +++ b/worklenz-frontend/public/locales/en/task-list-filters.json @@ -69,6 +69,7 @@ "cancel": "Cancel", "search": "Search", "groupedBy": "Grouped by", + "manage": "Manage", "manageStatuses": "Manage Statuses", "managePhases": "Manage Phases", "dragToReorderStatuses": "Statuses are organized by categories. Drag to reorder within categories. Click 'Add Status' to create new statuses in each category.", diff --git a/worklenz-frontend/public/locales/es/phases-drawer.json b/worklenz-frontend/public/locales/es/phases-drawer.json index abb6ee81..ed912ac7 100644 --- a/worklenz-frontend/public/locales/es/phases-drawer.json +++ b/worklenz-frontend/public/locales/es/phases-drawer.json @@ -1,13 +1,17 @@ { - "configurePhases": "Configurar fases", - "phaseLabel": "Etiqueta de fase", - "enterPhaseName": "Introducir nombre de la fase", - "addOption": "Agregar opción", - "phaseOptions": "Opciones de fase", + "configurePhases": "Configurar Fases", + "configure": "Configurar", + "phaseLabel": "Etiqueta de Fase", + "enterPhaseName": "Ingresa el nombre de la fase", + "addOption": "Agregar Opción", + "phaseOptions": "Opciones de Fase", + "optionsText": "Opciones", "dragToReorderPhases": "Arrastra las fases para reordenarlas. Cada fase puede tener un color diferente.", - "enterNewPhaseName": "Introducir nuevo nombre de fase...", - "addPhase": "Añadir Fase", + "enterNewPhaseName": "Ingresa el nombre de la nueva fase...", + "addPhase": "Agregar Fase", "noPhasesFound": "No se encontraron fases", + "no": "No", + "found": "encontrado", "deletePhase": "Eliminar Fase", "deletePhaseConfirm": "¿Estás seguro de que quieres eliminar esta fase? Esta acción no se puede deshacer.", "rename": "Renombrar", diff --git a/worklenz-frontend/public/locales/es/task-list-filters.json b/worklenz-frontend/public/locales/es/task-list-filters.json index dc42706a..00c27f16 100644 --- a/worklenz-frontend/public/locales/es/task-list-filters.json +++ b/worklenz-frontend/public/locales/es/task-list-filters.json @@ -69,8 +69,9 @@ "cancel": "Cancelar", "search": "Buscar", "groupedBy": "Agrupado por", - "manageStatuses": "Gestionar estados", - "managePhases": "Gestionar fases", + "manage": "Gestionar", + "manageStatuses": "Gestionar Estados", + "managePhases": "Gestionar Fases", "dragToReorderStatuses": "Los estados están organizados por categorías. Arrastra para reordenar dentro de las categorías. Haz clic en 'Agregar estado' para crear nuevos estados en cada categoría.", "enterNewStatusName": "Ingrese el nombre del nuevo estado...", "addStatus": "Agregar estado", diff --git a/worklenz-frontend/public/locales/pt/phases-drawer.json b/worklenz-frontend/public/locales/pt/phases-drawer.json index b0ca7c51..0d5b8cb7 100644 --- a/worklenz-frontend/public/locales/pt/phases-drawer.json +++ b/worklenz-frontend/public/locales/pt/phases-drawer.json @@ -1,13 +1,17 @@ { - "configurePhases": "Configurar fases", - "phaseLabel": "Etiqueta de fase", + "configurePhases": "Configurar Fases", + "configure": "Configurar", + "phaseLabel": "Rótulo da Fase", "enterPhaseName": "Digite o nome da fase", "addOption": "Adicionar Opção", "phaseOptions": "Opções de Fase", + "optionsText": "Opções", "dragToReorderPhases": "Arraste as fases para reordená-las. Cada fase pode ter uma cor diferente.", - "enterNewPhaseName": "Digite o novo nome da fase...", + "enterNewPhaseName": "Digite o nome da nova fase...", "addPhase": "Adicionar Fase", "noPhasesFound": "Nenhuma fase encontrada", + "no": "Nenhuma", + "found": "encontrada", "deletePhase": "Excluir Fase", "deletePhaseConfirm": "Tem certeza de que deseja excluir esta fase? Esta ação não pode ser desfeita.", "rename": "Renomear", diff --git a/worklenz-frontend/public/locales/pt/task-list-filters.json b/worklenz-frontend/public/locales/pt/task-list-filters.json index 49841ec5..3674a29a 100644 --- a/worklenz-frontend/public/locales/pt/task-list-filters.json +++ b/worklenz-frontend/public/locales/pt/task-list-filters.json @@ -69,8 +69,9 @@ "cancel": "Cancelar", "search": "Pesquisar", "groupedBy": "Agrupado por", - "manageStatuses": "Gerenciar status", - "managePhases": "Gerenciar fases", + "manage": "Gerenciar", + "manageStatuses": "Gerenciar Status", + "managePhases": "Gerenciar Fases", "dragToReorderStatuses": "Os status estão organizados por categorias. Arraste para reordenar dentro das categorias. Clique em 'Adicionar status' para criar novos status em cada categoria.", "enterNewStatusName": "Digite o nome do novo status...", "addStatus": "Adicionar status", diff --git a/worklenz-frontend/public/locales/zh/phases-drawer.json b/worklenz-frontend/public/locales/zh/phases-drawer.json index 8f55e527..37d68cfb 100644 --- a/worklenz-frontend/public/locales/zh/phases-drawer.json +++ b/worklenz-frontend/public/locales/zh/phases-drawer.json @@ -1,20 +1,24 @@ { - "configurePhases": "配置阶段", - "phaseLabel": "阶段标签", - "enterPhaseName": "输入阶段名称", - "addOption": "添加选项", - "phaseOptions": "阶段选项", - "dragToReorderPhases": "拖拽阶段以重新排序。每个阶段可以有不同的颜色。", - "enterNewPhaseName": "输入新阶段名称...", - "addPhase": "添加阶段", - "noPhasesFound": "未找到阶段", - "deletePhase": "删除阶段", - "deletePhaseConfirm": "您确定要删除此阶段吗?此操作无法撤销。", - "rename": "重命名", - "delete": "删除", - "create": "创建", - "cancel": "取消", - "selectColor": "选择颜色", - "managePhases": "管理阶段", - "close": "关闭" + "configurePhases": "配置阶段", + "configure": "配置", + "phaseLabel": "阶段标签", + "enterPhaseName": "输入阶段名称", + "addOption": "添加选项", + "phaseOptions": "阶段选项", + "optionsText": "选项", + "dragToReorderPhases": "拖拽阶段来重新排序。每个阶段可以有不同的颜色。", + "enterNewPhaseName": "输入新阶段名称...", + "addPhase": "添加阶段", + "noPhasesFound": "未找到阶段", + "no": "没有", + "found": "找到", + "deletePhase": "删除阶段", + "deletePhaseConfirm": "您确定要删除此阶段吗?此操作无法撤消。", + "rename": "重命名", + "delete": "删除", + "create": "创建", + "cancel": "取消", + "selectColor": "选择颜色", + "managePhases": "管理阶段", + "close": "关闭" } \ No newline at end of file diff --git a/worklenz-frontend/public/locales/zh/task-list-filters.json b/worklenz-frontend/public/locales/zh/task-list-filters.json index 50dcb8e6..4d1d6b43 100644 --- a/worklenz-frontend/public/locales/zh/task-list-filters.json +++ b/worklenz-frontend/public/locales/zh/task-list-filters.json @@ -62,7 +62,8 @@ "clearing": "清除中...", "cancel": "取消", "search": "搜索", - "groupedBy": "分组依据", + "groupedBy": "分组方式", + "manage": "管理", "manageStatuses": "管理状态", "managePhases": "管理阶段", "dragToReorderStatuses": "拖拽状态以重新排序。每个状态可以有不同的类别。", diff --git a/worklenz-frontend/src/api/taskAttributes/phases/phases.api.service.ts b/worklenz-frontend/src/api/taskAttributes/phases/phases.api.service.ts index 3c494049..fc47544a 100644 --- a/worklenz-frontend/src/api/taskAttributes/phases/phases.api.service.ts +++ b/worklenz-frontend/src/api/taskAttributes/phases/phases.api.service.ts @@ -1,12 +1,12 @@ -import apiClient from '@/api/api-client'; -import { API_BASE_URL } from '@/shared/constants'; import { IServerResponse } from '@/types/common.types'; +import apiClient from '@api/api-client'; +import { API_BASE_URL } from '@/shared/constants'; import { ITaskPhase } from '@/types/tasks/taskPhase.types'; import { toQueryString } from '@/utils/toQueryString'; const rootUrl = `${API_BASE_URL}/task-phases`; -interface UpdateSortOrderBody { +export interface UpdateSortOrderBody { from_index: number; to_index: number; phases: ITaskPhase[]; @@ -14,9 +14,10 @@ interface UpdateSortOrderBody { } export const phasesApiService = { - addPhaseOption: async (projectId: string) => { + addPhaseOption: async (projectId: string, name?: string) => { const q = toQueryString({ id: projectId, current_project_id: projectId }); - const response = await apiClient.post>(`${rootUrl}${q}`); + const body = name ? { name } : {}; + const response = await apiClient.post>(`${rootUrl}${q}`, body); return response.data; }, diff --git a/worklenz-frontend/src/components/enhanced-kanban/EnhancedKanbanCreateSection.tsx b/worklenz-frontend/src/components/enhanced-kanban/EnhancedKanbanCreateSection.tsx index 1c4d7087..eb9b87cc 100644 --- a/worklenz-frontend/src/components/enhanced-kanban/EnhancedKanbanCreateSection.tsx +++ b/worklenz-frontend/src/components/enhanced-kanban/EnhancedKanbanCreateSection.tsx @@ -139,7 +139,7 @@ const EnhancedKanbanCreateSection: React.FC = () => { } if (groupBy === IGroupBy.PHASE) { try { - const response = await phasesApiService.addPhaseOption(projectId); + const response = await phasesApiService.addPhaseOption(projectId, name); if (response.done && response.body) { dispatch(fetchEnhancedKanbanGroups(projectId)); } diff --git a/worklenz-frontend/src/components/task-management/ManagePhaseModal.css b/worklenz-frontend/src/components/task-management/ManagePhaseModal.css index e36bcd73..4d75b424 100644 --- a/worklenz-frontend/src/components/task-management/ManagePhaseModal.css +++ b/worklenz-frontend/src/components/task-management/ManagePhaseModal.css @@ -20,6 +20,112 @@ border-top: 1px solid #303030; } +/* Dark mode confirmation modal styling */ +.dark .ant-modal-confirm .ant-modal-content, +[data-theme="dark"] .ant-modal-confirm .ant-modal-content { + background-color: #1f1f1f !important; + border: 1px solid #303030 !important; +} + +.dark .ant-modal-confirm .ant-modal-header, +[data-theme="dark"] .ant-modal-confirm .ant-modal-header { + background-color: #1f1f1f !important; + border-bottom: 1px solid #303030 !important; +} + +.dark .ant-modal-confirm .ant-modal-body, +[data-theme="dark"] .ant-modal-confirm .ant-modal-body { + background-color: #1f1f1f !important; + color: #d9d9d9 !important; +} + +.dark .ant-modal-confirm .ant-modal-footer, +[data-theme="dark"] .ant-modal-confirm .ant-modal-footer { + background-color: #1f1f1f !important; + border-top: 1px solid #303030 !important; +} + +.dark .ant-modal-confirm .ant-modal-confirm-title, +[data-theme="dark"] .ant-modal-confirm .ant-modal-confirm-title { + color: #d9d9d9 !important; +} + +.dark .ant-modal-confirm .ant-modal-confirm-content, +[data-theme="dark"] .ant-modal-confirm .ant-modal-confirm-content { + color: #8c8c8c !important; +} + +.dark .ant-modal-confirm .ant-btn-default, +[data-theme="dark"] .ant-modal-confirm .ant-btn-default { + background-color: #141414 !important; + border-color: #303030 !important; + color: #d9d9d9 !important; +} + +.dark .ant-modal-confirm .ant-btn-default:hover, +[data-theme="dark"] .ant-modal-confirm .ant-btn-default:hover { + background-color: #262626 !important; + border-color: #40a9ff !important; + color: #d9d9d9 !important; +} + +.dark .ant-modal-confirm .ant-btn-primary, +[data-theme="dark"] .ant-modal-confirm .ant-btn-primary { + background-color: #1890ff !important; + border-color: #1890ff !important; + color: #ffffff !important; +} + +.dark .ant-modal-confirm .ant-btn-primary:hover, +[data-theme="dark"] .ant-modal-confirm .ant-btn-primary:hover { + background-color: #40a9ff !important; + border-color: #40a9ff !important; + color: #ffffff !important; +} + +.dark .ant-modal-confirm .ant-btn-dangerous, +[data-theme="dark"] .ant-modal-confirm .ant-btn-dangerous { + background-color: #ff4d4f !important; + border-color: #ff4d4f !important; + color: #ffffff !important; +} + +.dark .ant-modal-confirm .ant-btn-dangerous:hover, +[data-theme="dark"] .ant-modal-confirm .ant-btn-dangerous:hover { + background-color: #ff7875 !important; + border-color: #ff7875 !important; + color: #ffffff !important; +} + +/* Light mode confirmation modal styling (ensure consistency) */ +.ant-modal-confirm .ant-modal-content { + background-color: #ffffff; + border: 1px solid #f0f0f0; +} + +.ant-modal-confirm .ant-modal-header { + background-color: #ffffff; + border-bottom: 1px solid #f0f0f0; +} + +.ant-modal-confirm .ant-modal-body { + background-color: #ffffff; + color: #262626; +} + +.ant-modal-confirm .ant-modal-footer { + background-color: #ffffff; + border-top: 1px solid #f0f0f0; +} + +.ant-modal-confirm .ant-modal-confirm-title { + color: #262626; +} + +.ant-modal-confirm .ant-modal-confirm-content { + color: #595959; +} + .dark-modal .ant-form-item-label > label { color: #d9d9d9; } diff --git a/worklenz-frontend/src/components/task-management/ManagePhaseModal.tsx b/worklenz-frontend/src/components/task-management/ManagePhaseModal.tsx index 81a44378..e746851c 100644 --- a/worklenz-frontend/src/components/task-management/ManagePhaseModal.tsx +++ b/worklenz-frontend/src/components/task-management/ManagePhaseModal.tsx @@ -18,6 +18,7 @@ import { deletePhaseOption, updatePhaseColor, } from '@/features/projects/singleProject/phase/phases.slice'; +import { updatePhaseLabel } from '@/features/project/project.slice'; import { ITaskPhase } from '@/types/tasks/taskPhase.types'; import { Modal as AntModal } from 'antd'; import { fetchTasksV3 } from '@/features/task-management/task-management.slice'; @@ -307,7 +308,7 @@ const ManagePhaseModal: React.FC = ({ if (!newPhaseName.trim() || !finalProjectId) return; try { - await dispatch(addPhaseOption({ projectId: finalProjectId })); + await dispatch(addPhaseOption({ projectId: finalProjectId, name: newPhaseName.trim() })); await dispatch(fetchPhasesByProjectId(finalProjectId)); await refreshTasks(); setNewPhaseName(''); @@ -408,6 +409,7 @@ const ManagePhaseModal: React.FC = ({ ).unwrap(); if (res.done) { + dispatch(updatePhaseLabel(phaseName)); setInitialPhaseName(phaseName); await refreshTasks(); } @@ -428,7 +430,7 @@ const ManagePhaseModal: React.FC = ({ - {t('configurePhases')} + {t('configure')} {phaseName || project?.phase_label || t('phasesText')} } open={open} @@ -495,7 +497,7 @@ const ManagePhaseModal: React.FC = ({ - 🎨 Drag phases to reorder them. Click on a phase name to rename it. Each phase can have a custom color. + 🎨 Drag {(phaseName || project?.phase_label || t('phasesText')).toLowerCase()} to reorder them. Click on a {(phaseName || project?.phase_label || t('phaseText')).toLowerCase()} name to rename it. Each {(phaseName || project?.phase_label || t('phaseText')).toLowerCase()} can have a custom color. @@ -558,7 +560,7 @@ const ManagePhaseModal: React.FC = ({ - {t('phaseOptions')} + {phaseName || project?.phase_label || t('phasesText')} {t('optionsText')} )} {section.selectedValues[0] === 'status' && ( @@ -994,6 +996,7 @@ const ImprovedTaskFilters: React.FC = ({ position, cla const isDarkMode = useAppSelector(state => state.themeReducer?.mode === 'dark'); const { projectId } = useAppSelector(state => state.projectReducer); const { projectView } = useTabSearchParam(); + const projectPhaseLabel = useAppSelector(state => state.projectReducer.project?.phase_label); // Theme-aware class names - memoize to prevent unnecessary re-renders // Using greyish colors for both dark and light modes @@ -1298,6 +1301,7 @@ const ImprovedTaskFilters: React.FC = ({ position, cla dispatch={dispatch} onManageStatus={() => setShowManageStatusModal(true)} onManagePhase={() => setShowManagePhaseModal(true)} + projectPhaseLabel={projectPhaseLabel} /> )) ) : ( diff --git a/worklenz-frontend/src/features/projects/singleProject/phase/PhaseHeader.tsx b/worklenz-frontend/src/features/projects/singleProject/phase/PhaseHeader.tsx index 4607ae35..e10df057 100644 --- a/worklenz-frontend/src/features/projects/singleProject/phase/PhaseHeader.tsx +++ b/worklenz-frontend/src/features/projects/singleProject/phase/PhaseHeader.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import { useSelectedProject } from '../../../../hooks/useSelectedProject'; import { useAppSelector } from '../../../../hooks/useAppSelector'; import { Flex } from 'antd'; import ConfigPhaseButton from './ConfigPhaseButton'; @@ -10,19 +9,13 @@ const PhaseHeader = () => { // localization const { t } = useTranslation('task-list-filters'); - // get selected project for useSelectedProject hook - const selectedProject = useSelectedProject(); - - // get phase data from redux - const phaseList = useAppSelector(state => state.phaseReducer.phaseList); - - //get phases details from phases slice - const phase = phaseList.find(el => el.projectId === selectedProject?.projectId); + // get project data from redux + const { project } = useAppSelector(state => state.projectReducer); return ( - {phase?.phase || t('phasesText')} - + {project?.phase_label || t('phasesText')} + ); }; diff --git a/worklenz-frontend/src/features/projects/singleProject/phase/phases.slice.ts b/worklenz-frontend/src/features/projects/singleProject/phase/phases.slice.ts index 050c5765..304a1635 100644 --- a/worklenz-frontend/src/features/projects/singleProject/phase/phases.slice.ts +++ b/worklenz-frontend/src/features/projects/singleProject/phase/phases.slice.ts @@ -16,9 +16,9 @@ const initialState: PhaseState = { export const addPhaseOption = createAsyncThunk( 'phase/addPhaseOption', - async ({ projectId }: { projectId: string }, { rejectWithValue }) => { + async ({ projectId, name }: { projectId: string; name?: string }, { rejectWithValue }) => { try { - const response = await phasesApiService.addPhaseOption(projectId); + const response = await phasesApiService.addPhaseOption(projectId, name); return response; } catch (error) { return rejectWithValue(error); diff --git a/worklenz-frontend/src/pages/projects/projectView/board/board-section/board-section-card/board-create-section-card.tsx b/worklenz-frontend/src/pages/projects/projectView/board/board-section/board-section-card/board-create-section-card.tsx index 5abae368..7e61385e 100644 --- a/worklenz-frontend/src/pages/projects/projectView/board/board-section/board-section-card/board-create-section-card.tsx +++ b/worklenz-frontend/src/pages/projects/projectView/board/board-section/board-section-card/board-create-section-card.tsx @@ -106,13 +106,8 @@ const BoardCreateSectionCard = () => { } if (groupBy === IGroupBy.PHASE && projectId) { - const body = { - name: sectionName, - project_id: projectId, - }; - try { - const response = await phasesApiService.addPhaseOption(projectId); + const response = await phasesApiService.addPhaseOption(projectId, sectionName); if (response.done && response.body) { dispatch(fetchBoardTaskGroups(projectId)); } diff --git a/worklenz-frontend/src/styles/task-management.css b/worklenz-frontend/src/styles/task-management.css index 1cfc2669..c4982dac 100644 --- a/worklenz-frontend/src/styles/task-management.css +++ b/worklenz-frontend/src/styles/task-management.css @@ -4,6 +4,152 @@ width: 100%; } +/* Global Confirmation Modal Styles */ +/* Light mode confirmation modal styling (default) */ +.ant-modal-confirm .ant-modal-content { + background-color: #ffffff; + border: 1px solid #f0f0f0; +} + +.ant-modal-confirm .ant-modal-header { + background-color: #ffffff; + border-bottom: 1px solid #f0f0f0; +} + +.ant-modal-confirm .ant-modal-body { + background-color: #ffffff; + color: #262626; +} + +.ant-modal-confirm .ant-modal-footer { + background-color: #ffffff; + border-top: 1px solid #f0f0f0; +} + +.ant-modal-confirm .ant-modal-confirm-title { + color: #262626; +} + +.ant-modal-confirm .ant-modal-confirm-content { + color: #595959; +} + +/* Dark mode confirmation modal styling */ +.dark .ant-modal-confirm .ant-modal-content, +[data-theme="dark"] .ant-modal-confirm .ant-modal-content, +html.dark .ant-modal-confirm .ant-modal-content { + background-color: #1f1f1f !important; + border: 1px solid #303030 !important; +} + +.dark .ant-modal-confirm .ant-modal-header, +[data-theme="dark"] .ant-modal-confirm .ant-modal-header, +html.dark .ant-modal-confirm .ant-modal-header { + background-color: #1f1f1f !important; + border-bottom: 1px solid #303030 !important; +} + +.dark .ant-modal-confirm .ant-modal-body, +[data-theme="dark"] .ant-modal-confirm .ant-modal-body, +html.dark .ant-modal-confirm .ant-modal-body { + background-color: #1f1f1f !important; + color: #d9d9d9 !important; +} + +.dark .ant-modal-confirm .ant-modal-footer, +[data-theme="dark"] .ant-modal-confirm .ant-modal-footer, +html.dark .ant-modal-confirm .ant-modal-footer { + background-color: #1f1f1f !important; + border-top: 1px solid #303030 !important; +} + +.dark .ant-modal-confirm .ant-modal-confirm-title, +[data-theme="dark"] .ant-modal-confirm .ant-modal-confirm-title, +html.dark .ant-modal-confirm .ant-modal-confirm-title { + color: #d9d9d9 !important; +} + +.dark .ant-modal-confirm .ant-modal-confirm-content, +[data-theme="dark"] .ant-modal-confirm .ant-modal-confirm-content, +html.dark .ant-modal-confirm .ant-modal-confirm-content { + color: #8c8c8c !important; +} + +.dark .ant-modal-confirm .ant-btn-default, +[data-theme="dark"] .ant-modal-confirm .ant-btn-default, +html.dark .ant-modal-confirm .ant-btn-default { + background-color: #141414 !important; + border-color: #303030 !important; + color: #d9d9d9 !important; +} + +.dark .ant-modal-confirm .ant-btn-default:hover, +[data-theme="dark"] .ant-modal-confirm .ant-btn-default:hover, +html.dark .ant-modal-confirm .ant-btn-default:hover { + background-color: #262626 !important; + border-color: #40a9ff !important; + color: #d9d9d9 !important; +} + +.dark .ant-modal-confirm .ant-btn-primary, +[data-theme="dark"] .ant-modal-confirm .ant-btn-primary, +html.dark .ant-modal-confirm .ant-btn-primary { + background-color: #1890ff !important; + border-color: #1890ff !important; + color: #ffffff !important; +} + +.dark .ant-modal-confirm .ant-btn-primary:hover, +[data-theme="dark"] .ant-modal-confirm .ant-btn-primary:hover, +html.dark .ant-modal-confirm .ant-btn-primary:hover { + background-color: #40a9ff !important; + border-color: #40a9ff !important; + color: #ffffff !important; +} + +.dark .ant-modal-confirm .ant-btn-dangerous, +[data-theme="dark"] .ant-modal-confirm .ant-btn-dangerous, +html.dark .ant-modal-confirm .ant-btn-dangerous { + background-color: #ff4d4f !important; + border-color: #ff4d4f !important; + color: #ffffff !important; +} + +.dark .ant-modal-confirm .ant-btn-dangerous:hover, +[data-theme="dark"] .ant-modal-confirm .ant-btn-dangerous:hover, +html.dark .ant-modal-confirm .ant-btn-dangerous:hover { + background-color: #ff7875 !important; + border-color: #ff7875 !important; + color: #ffffff !important; +} + +/* Error modal specific styling */ +.dark .ant-modal-error .ant-modal-content, +[data-theme="dark"] .ant-modal-error .ant-modal-content, +html.dark .ant-modal-error .ant-modal-content { + background-color: #1f1f1f !important; + border: 1px solid #303030 !important; +} + +.dark .ant-modal-error .ant-modal-body, +[data-theme="dark"] .ant-modal-error .ant-modal-body, +html.dark .ant-modal-error .ant-modal-body { + background-color: #1f1f1f !important; + color: #d9d9d9 !important; +} + +.dark .ant-modal-error .ant-modal-confirm-title, +[data-theme="dark"] .ant-modal-error .ant-modal-confirm-title, +html.dark .ant-modal-error .ant-modal-confirm-title { + color: #d9d9d9 !important; +} + +.dark .ant-modal-error .ant-modal-confirm-content, +[data-theme="dark"] .ant-modal-error .ant-modal-content, +html.dark .ant-modal-error .ant-modal-confirm-content { + color: #8c8c8c !important; +} + .task-group { transition: all 0.2s ease; }