mirror of
https://github.com/nowcommunity/nowdatabase.git
synced 2026-10-12 19:13:52 +03:00
update project update prosess in frontend, and add project validators
This commit is contained in:
@@ -1,12 +1,20 @@
|
|||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import { useNavigate, useParams } from 'react-router-dom'
|
import { useNavigate, useParams } from 'react-router-dom'
|
||||||
import { CircularProgress } from '@mui/material'
|
|
||||||
import { DetailView, TabType } from '../DetailView/DetailView'
|
|
||||||
import { CoordinatorTab } from './Tabs/CoordinatorTab'
|
|
||||||
import { useDeleteProjectMutation, useGetProjectDetailsQuery, useUpdateProjectMutation } from '@/redux/projectReducer'
|
|
||||||
import { useNotify } from '@/hooks/notification'
|
import { useNotify } from '@/hooks/notification'
|
||||||
import { useUsersApi } from '@/hooks/useUsersApi'
|
import { useUsersApi } from '@/hooks/useUsersApi'
|
||||||
import { mapProjectEditDataToUpdatePayload } from '@/api/projectsApi'
|
import {
|
||||||
|
UpdateProjectPayload,
|
||||||
|
useDeleteProjectMutation,
|
||||||
|
useGetProjectDetailsQuery,
|
||||||
|
useUpdateProjectMutation,
|
||||||
|
} from '@/redux/projectReducer'
|
||||||
|
import { ProjectPeople, RowState } from '@/shared/types'
|
||||||
|
import { CircularProgress } from '@mui/material'
|
||||||
|
|
||||||
|
import { DetailView, TabType } from '../DetailView/DetailView'
|
||||||
|
import { CoordinatorTab } from './Tabs/CoordinatorTab'
|
||||||
|
|
||||||
import type { EditDataType, ProjectDetailsType } from '@/shared/types'
|
import type { EditDataType, ProjectDetailsType } from '@/shared/types'
|
||||||
import type { ValidationObject } from '@/shared/validators/validator'
|
import type { ValidationObject } from '@/shared/validators/validator'
|
||||||
import type { FetchBaseQueryError } from '@reduxjs/toolkit/query'
|
import type { FetchBaseQueryError } from '@reduxjs/toolkit/query'
|
||||||
@@ -56,15 +64,54 @@ export const ProjectDetails = () => {
|
|||||||
error: null,
|
error: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const createProjectUpdatePayload = (editData: EditDataType<ProjectDetailsType>): UpdateProjectPayload | null => {
|
||||||
|
const userOption = users.find(user => user.initials === editData.contact)
|
||||||
|
if (!userOption) {
|
||||||
|
notify('Could not find selected coordinator.', 'error')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const isRemoved = (member: EditDataType<ProjectPeople>) => {
|
||||||
|
const state = (member as EditDataType<ProjectPeople> & { rowState?: RowState }).rowState
|
||||||
|
return state === 'removed' || state === 'cancelled'
|
||||||
|
}
|
||||||
|
|
||||||
|
const memberUserIds = Array.from(
|
||||||
|
new Set(
|
||||||
|
(editData.now_proj_people ?? [])
|
||||||
|
.filter(member => !isRemoved(member))
|
||||||
|
.map(member => {
|
||||||
|
const userIdFromPeople = (member.com_people as { user_id?: number } | undefined)?.user_id
|
||||||
|
const userIdFromRelation = member.com_people?.user?.user_id
|
||||||
|
if (typeof userIdFromPeople === 'number') return userIdFromPeople
|
||||||
|
if (typeof userIdFromRelation === 'number') return userIdFromRelation
|
||||||
|
return users.find(user => user.initials === member.initials) ?? null
|
||||||
|
})
|
||||||
|
.filter((id): id is number => typeof id === 'number')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
pid: editData.pid!,
|
||||||
|
projectCode: editData.proj_code!,
|
||||||
|
projectName: editData.proj_name!,
|
||||||
|
coordinatorUserId: userOption.userId,
|
||||||
|
projectStatus: editData.proj_status!,
|
||||||
|
recordStatus: editData.proj_records!,
|
||||||
|
memberUserIds,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const onWrite = async (editData: EditDataType<ProjectDetailsType>) => {
|
const onWrite = async (editData: EditDataType<ProjectDetailsType>) => {
|
||||||
if (!projectId) return
|
if (!projectId) return
|
||||||
const payload = mapProjectEditDataToUpdatePayload(editData, users)
|
|
||||||
|
|
||||||
|
const payload = createProjectUpdatePayload(editData)
|
||||||
if (!payload) {
|
if (!payload) {
|
||||||
notify('Coordinator selection is required to save project changes.', 'error')
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(editData)
|
||||||
|
console.log(payload)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await updateProject(payload).unwrap()
|
await updateProject(payload).unwrap()
|
||||||
notify('Saved project successfully.')
|
notify('Saved project successfully.')
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ export const CoordinatorTab = () => {
|
|||||||
|
|
||||||
const projectInformation = [
|
const projectInformation = [
|
||||||
['Project Id', textField('pid', { type: 'text', readonly: true, disabled: true })],
|
['Project Id', textField('pid', { type: 'text', readonly: true, disabled: true })],
|
||||||
['Project Code', textField('proj_code')],
|
['Project Code', textField('proj_code', { trim: true })],
|
||||||
['Project Name', textField('proj_name')],
|
['Project Name', textField('proj_name', { trim: true })],
|
||||||
['Coordinator', <CoordinatorSelect key="coordinator-select" variant="detail" />],
|
['Coordinator', <CoordinatorSelect key="coordinator-select" variant="detail" />],
|
||||||
[
|
[
|
||||||
'Project Status',
|
'Project Status',
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import { EditDataType, Project } from '../types'
|
||||||
|
import { Validators, validateFields, validator } from './validator'
|
||||||
|
|
||||||
|
/*
|
||||||
|
pid: number;
|
||||||
|
contact: string;
|
||||||
|
proj_code: string | null;
|
||||||
|
proj_name: string | null;
|
||||||
|
proj_status: string | null;
|
||||||
|
proj_records: boolean | null;
|
||||||
|
*/
|
||||||
|
|
||||||
|
const projectValidators: Validators<Partial<EditDataType<Project>>> = {
|
||||||
|
pid: {
|
||||||
|
name: 'Project Id',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
contact: {
|
||||||
|
name: 'Coordinator',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
proj_code: {
|
||||||
|
name: 'Project Code',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
proj_name: {
|
||||||
|
name: 'Project Name',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
proj_status: {
|
||||||
|
name: 'Project Status',
|
||||||
|
required: true,
|
||||||
|
asString: value => {
|
||||||
|
if (!['current', 'no_data', 'finished'].includes(value))
|
||||||
|
return 'Project Status must be one of the following: "current", "no_data", or "finished".'
|
||||||
|
return null
|
||||||
|
},
|
||||||
|
},
|
||||||
|
proj_records: {
|
||||||
|
name: 'Record Status',
|
||||||
|
required: true,
|
||||||
|
asString: value => {
|
||||||
|
if (!['public', 'private'].includes(value)) return 'Record Status must be either true or false.'
|
||||||
|
return null
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const validateProject = (editData: EditDataType<Project>, fieldName: keyof EditDataType<Project>) => {
|
||||||
|
return validator<EditDataType<Project>>(projectValidators, editData, fieldName)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const validateProjectFields = (editData: Partial<EditDataType<Project>>) =>
|
||||||
|
validateFields<EditDataType<Project>>(projectValidators, editData)
|
||||||
Reference in New Issue
Block a user