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 { 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 { 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 { ValidationObject } from '@/shared/validators/validator'
|
||||
import type { FetchBaseQueryError } from '@reduxjs/toolkit/query'
|
||||
@@ -56,15 +64,54 @@ export const ProjectDetails = () => {
|
||||
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>) => {
|
||||
if (!projectId) return
|
||||
const payload = mapProjectEditDataToUpdatePayload(editData, users)
|
||||
|
||||
const payload = createProjectUpdatePayload(editData)
|
||||
if (!payload) {
|
||||
notify('Coordinator selection is required to save project changes.', 'error')
|
||||
return
|
||||
}
|
||||
|
||||
console.log(editData)
|
||||
console.log(payload)
|
||||
|
||||
try {
|
||||
await updateProject(payload).unwrap()
|
||||
notify('Saved project successfully.')
|
||||
|
||||
@@ -9,8 +9,8 @@ export const CoordinatorTab = () => {
|
||||
|
||||
const projectInformation = [
|
||||
['Project Id', textField('pid', { type: 'text', readonly: true, disabled: true })],
|
||||
['Project Code', textField('proj_code')],
|
||||
['Project Name', textField('proj_name')],
|
||||
['Project Code', textField('proj_code', { trim: true })],
|
||||
['Project Name', textField('proj_name', { trim: true })],
|
||||
['Coordinator', <CoordinatorSelect key="coordinator-select" variant="detail" />],
|
||||
[
|
||||
'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