@@ -84,6 +84,8 @@ export interface CreateProjectResponse { | |||
category: string; | |||
team: string; | |||
client: string; | |||
message: string; | |||
errorPosition: string; | |||
} | |||
export const saveProject = async (data: CreateProjectInputs) => { | |||
@@ -81,7 +81,7 @@ const hasErrorsInTab = ( | |||
switch (tabIndex) { | |||
case 0: | |||
return ( | |||
errors.projectName || errors.projectDescription || errors.clientId | |||
errors.projectName || errors.projectDescription || errors.clientId || errors.projectCode | |||
); | |||
case 2: | |||
return ( | |||
@@ -230,12 +230,17 @@ const CreateProject: React.FC<Props> = ({ | |||
data.taskTemplateId = data.taskTemplateId === "All" ? undefined : data.taskTemplateId; | |||
const response = await saveProject(data); | |||
if (response.id > 0) { | |||
if (response.id > 0 && response.message?.toLowerCase() === "success" && response.errorPosition === null) { | |||
successDialog(successTitle, t).then(() => { | |||
router.replace("/projects"); | |||
}); | |||
} else { | |||
errorDialog(errorTitle, t).then(() => { | |||
errorDialog(response.message ?? errorTitle, t).then(() => { | |||
if (response.errorPosition !== null && response.errorPosition === "projectCode") { | |||
formProps.setError("projectCode", { message: response.message, type: "invalid" }) | |||
setTabIndex(0) | |||
} | |||
return false; | |||
}); | |||
} | |||
@@ -257,7 +262,7 @@ const CreateProject: React.FC<Props> = ({ | |||
if ( | |||
errors.projectName || | |||
errors.projectDescription || | |||
// errors.projectCode || | |||
errors.projectCode || | |||
errors.clientId | |||
) { | |||
setTabIndex(0); | |||
@@ -216,13 +216,13 @@ const ProjectClientDetails: React.FC<Props> = ({ | |||
<TextField | |||
label={t("Project Code")} | |||
fullWidth | |||
disabled | |||
disabled={isSubProject && mainProjects !== undefined} | |||
{...register("projectCode", | |||
// { | |||
// required: "Project code required!", | |||
// } | |||
{ | |||
required: !(isSubProject && mainProjects !== undefined) && "Project code required!", | |||
} | |||
)} | |||
// error={Boolean(errors.projectCode)} | |||
error={Boolean(errors.projectCode)} | |||
/> | |||
</Grid> | |||
<Grid item xs={6}> | |||
@@ -348,6 +348,7 @@ const ProjectClientDetails: React.FC<Props> = ({ | |||
<Checkbox | |||
{...register("isClpProject")} | |||
checked={Boolean(watch("isClpProject"))} | |||
disabled={isSubProject && mainProjects !== undefined} | |||
/> | |||
<Typography variant="overline" display="inline"> | |||
{t("CLP Project")} | |||
@@ -67,6 +67,7 @@ import { | |||
MAINTAIN_TEAM, | |||
MAINTAIN_GROUP, | |||
MAINTAIN_HOLIDAY, | |||
VIEW_PROJECT_RESOURCE_CONSUMPTION_RANKING, | |||
} from "@/middleware"; | |||
import { SessionWithAbilities } from "../AppBar/NavigationToggle"; | |||
import { authOptions } from "@/config/authConfig"; | |||
@@ -131,6 +132,9 @@ const NavigationContent: React.FC<Props> = ({ abilities, username }) => { | |||
icon: <AccountTreeIcon />, | |||
label: "Project Resource Consumption Ranking", | |||
path: "/dashboard/ProjectResourceConsumptionRanking", | |||
isHidden: ![VIEW_PROJECT_RESOURCE_CONSUMPTION_RANKING].some((ability) => | |||
abilities!.includes(ability), | |||
) | |||
}, | |||
{ | |||
icon: <PeopleIcon />, | |||
@@ -273,7 +277,7 @@ const NavigationContent: React.FC<Props> = ({ abilities, username }) => { | |||
abilities!.includes(ability), | |||
), | |||
children: [ | |||
{ | |||
{ | |||
icon: <GroupIcon />, | |||
label: "Client", | |||
path: "/settings/customer", | |||
@@ -285,19 +289,19 @@ const NavigationContent: React.FC<Props> = ({ abilities, username }) => { | |||
path: "/settings/subsidiary", | |||
isHidden: ![VIEW_SUBSIDIARY, MAINTAIN_SUBSIDIARY].some((ability) => abilities!.includes(ability),), | |||
}, | |||
{ | |||
icon: <Staff />, | |||
label: "Staff", | |||
{ | |||
icon: <Staff />, | |||
label: "Staff", | |||
path: "/settings/staff", | |||
isHidden: ![VIEW_STAFF, MAINTAIN_STAFF].some((ability) => abilities!.includes(ability),), | |||
}, | |||
{ | |||
{ | |||
icon: <Company />, | |||
label: "Company", | |||
path: "/settings/company", | |||
isHidden: ![VIEW_COMPANY, MAINTAIN_COMPANY].some((ability) => abilities!.includes(ability),), | |||
}, | |||
{ | |||
{ | |||
icon: <EmojiEventsIcon />, | |||
label: "Skill", | |||
path: "/settings/skill", | |||
@@ -309,19 +313,19 @@ const NavigationContent: React.FC<Props> = ({ abilities, username }) => { | |||
path: "/settings/department", | |||
isHidden: ![VIEW_DEPARTMENT, MAINTAIN_DEPARTMENT].some((ability) => abilities!.includes(ability),), | |||
}, | |||
{ | |||
{ | |||
icon: <Position />, | |||
label: "Position", | |||
path: "/settings/position", | |||
isHidden: ![VIEW_POSITION, MAINTAIN_POSITION].some((ability) => abilities!.includes(ability),), | |||
}, | |||
{ | |||
{ | |||
icon: <Salary />, | |||
label: "Salary", | |||
path: "/settings/salary", | |||
isHidden: ![VIEW_SALARY, MAINTAIN_SALARY].some((ability) => abilities!.includes(ability),), | |||
}, | |||
{ | |||
{ | |||
icon: <Team />, | |||
label: "Team", | |||
path: "/settings/team", | |||
@@ -334,7 +338,7 @@ const NavigationContent: React.FC<Props> = ({ abilities, username }) => { | |||
path: "/settings/group", | |||
isHidden: ![VIEW_GROUP, MAINTAIN_GROUP].some((ability) => abilities!.includes(ability),), | |||
}, | |||
{ | |||
{ | |||
icon: <Holiday />, | |||
label: "Holiday", | |||
path: "/settings/holiday", | |||
@@ -57,6 +57,7 @@ export const [ | |||
MAINTAIN_PROJECT, | |||
DELETE_PROJECT, | |||
MAINTAIN_TIMESHEET_FAST_TIME_ENTRY, | |||
VIEW_PROJECT_RESOURCE_CONSUMPTION_RANKING, | |||
] = [ | |||
'MAINTAIN_USER', | |||
'MAINTAIN_TIMESHEET', | |||
@@ -94,7 +95,8 @@ export const [ | |||
'VIEW_PROJECT', | |||
'MAINTAIN_PROJECT', | |||
'DELETE_PROJECT', | |||
'MAINTAIN_TIMESHEET_FAST_TIME_ENTRY' | |||
'MAINTAIN_TIMESHEET_FAST_TIME_ENTRY', | |||
'VIEW_PROJECT_RESOURCE_CONSUMPTION_RANKING' | |||
] | |||
const PRIVATE_ROUTES = [ | |||
@@ -233,6 +235,9 @@ export default async function middleware( | |||
isAuth = [VIEW_DASHBOARD_ALL, VIEW_DASHBOARD_SELF].some((ability) => abilities.includes(ability)); | |||
} | |||
if (req.nextUrl.pathname.startsWith('/dashboard/ProjectResourceConsumptionRanking')) { | |||
isAuth = [VIEW_PROJECT_RESOURCE_CONSUMPTION_RANKING].some((ability) => abilities.includes(ability)); | |||
} | |||
return isAuth | |||
} | |||
} | |||