feat(project-drawer): enhance project data fetching and error handling
- Updated project data fetching logic in the project drawer and related components to ensure the drawer opens only after successful data retrieval. - Added detailed logging for successful and failed fetch attempts to improve debugging and user feedback. - Introduced error handling to maintain user experience by allowing the drawer to open even if data fetching fails, displaying an error state. - Refactored project list and project view components to optimize search functionality and improve loading states. - Removed deprecated components related to task management to streamline the project view.
This commit is contained in:
@@ -124,10 +124,25 @@ const ProjectGroupList: React.FC<ProjectGroupListProps> = ({
|
||||
// Action handlers
|
||||
const handleSettingsClick = (e: React.MouseEvent, projectId: string) => {
|
||||
e.stopPropagation();
|
||||
console.log('Opening project drawer from project group for project:', projectId);
|
||||
trackMixpanelEvent(evt_projects_settings_click);
|
||||
|
||||
// Set project ID first
|
||||
dispatch(setProjectId(projectId));
|
||||
dispatch(fetchProjectData(projectId));
|
||||
dispatch(toggleProjectDrawer());
|
||||
|
||||
// Then fetch project data
|
||||
dispatch(fetchProjectData(projectId))
|
||||
.unwrap()
|
||||
.then((projectData) => {
|
||||
console.log('Project data fetched successfully from project group:', projectData);
|
||||
// Open drawer after data is fetched
|
||||
dispatch(toggleProjectDrawer());
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Failed to fetch project data from project group:', error);
|
||||
// Still open drawer even if fetch fails, so user can see error state
|
||||
dispatch(toggleProjectDrawer());
|
||||
});
|
||||
};
|
||||
|
||||
const handleArchiveClick = async (
|
||||
|
||||
@@ -46,10 +46,25 @@ export const ActionButtons: React.FC<ActionButtonsProps> = ({
|
||||
|
||||
const handleSettingsClick = () => {
|
||||
if (record.id) {
|
||||
console.log('Opening project drawer for project:', record.id);
|
||||
trackMixpanelEvent(evt_projects_settings_click);
|
||||
|
||||
// Set project ID first
|
||||
dispatch(setProjectId(record.id));
|
||||
dispatch(fetchProjectData(record.id));
|
||||
dispatch(toggleProjectDrawer());
|
||||
|
||||
// Then fetch project data
|
||||
dispatch(fetchProjectData(record.id))
|
||||
.unwrap()
|
||||
.then((projectData) => {
|
||||
console.log('Project data fetched successfully:', projectData);
|
||||
// Open drawer after data is fetched
|
||||
dispatch(toggleProjectDrawer());
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Failed to fetch project data:', error);
|
||||
// Still open drawer even if fetch fails, so user can see error state
|
||||
dispatch(toggleProjectDrawer());
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ const ProjectDrawer = ({ onClose }: { onClose: () => void }) => {
|
||||
null
|
||||
);
|
||||
const [isFormValid, setIsFormValid] = useState<boolean>(true);
|
||||
const [drawerVisible, setDrawerVisible] = useState<boolean>(false);
|
||||
|
||||
// Selectors
|
||||
const { clients, loading: loadingClients } = useAppSelector(state => state.clientReducer);
|
||||
@@ -131,6 +132,60 @@ const ProjectDrawer = ({ onClose }: { onClose: () => void }) => {
|
||||
loadInitialData();
|
||||
}, [dispatch]);
|
||||
|
||||
// New effect to handle form population when project data becomes available
|
||||
useEffect(() => {
|
||||
if (drawerVisible && projectId && project && !projectLoading) {
|
||||
console.log('Populating form with project data:', project);
|
||||
setEditMode(true);
|
||||
|
||||
try {
|
||||
form.setFieldsValue({
|
||||
...project,
|
||||
start_date: project.start_date ? dayjs(project.start_date) : null,
|
||||
end_date: project.end_date ? dayjs(project.end_date) : null,
|
||||
working_days: project.working_days || 0,
|
||||
use_manual_progress: project.use_manual_progress || false,
|
||||
use_weighted_progress: project.use_weighted_progress || false,
|
||||
use_time_progress: project.use_time_progress || false,
|
||||
});
|
||||
|
||||
setSelectedProjectManager(project.project_manager || null);
|
||||
setLoading(false);
|
||||
console.log('Form populated successfully with project data');
|
||||
} catch (error) {
|
||||
console.error('Error setting form values:', error);
|
||||
logger.error('Error setting form values in project drawer', error);
|
||||
setLoading(false);
|
||||
}
|
||||
} else if (drawerVisible && !projectId) {
|
||||
// Creating new project
|
||||
console.log('Setting up drawer for new project creation');
|
||||
setEditMode(false);
|
||||
setLoading(false);
|
||||
} else if (drawerVisible && projectId && !project && !projectLoading) {
|
||||
// Project data failed to load or is empty
|
||||
console.warn('Project drawer is visible but no project data available');
|
||||
setLoading(false);
|
||||
} else if (drawerVisible && projectId) {
|
||||
console.log('Drawer visible, waiting for project data to load...');
|
||||
}
|
||||
}, [drawerVisible, projectId, project, projectLoading, form]);
|
||||
|
||||
// Additional effect to handle loading state when project data is being fetched
|
||||
useEffect(() => {
|
||||
if (drawerVisible && projectId && projectLoading) {
|
||||
console.log('Project data is loading, maintaining loading state');
|
||||
setLoading(true);
|
||||
}
|
||||
}, [drawerVisible, projectId, projectLoading]);
|
||||
|
||||
// Define resetForm function early to avoid declaration order issues
|
||||
const resetForm = useCallback(() => {
|
||||
setEditMode(false);
|
||||
form.resetFields();
|
||||
setSelectedProjectManager(null);
|
||||
}, [form]);
|
||||
|
||||
useEffect(() => {
|
||||
const startDate = form.getFieldValue('start_date');
|
||||
const endDate = form.getFieldValue('end_date');
|
||||
@@ -226,47 +281,33 @@ const ProjectDrawer = ({ onClose }: { onClose: () => void }) => {
|
||||
return workingDays;
|
||||
};
|
||||
|
||||
// Improved handleVisibilityChange to track drawer state without doing form operations
|
||||
const handleVisibilityChange = useCallback(
|
||||
(visible: boolean) => {
|
||||
if (visible && projectId) {
|
||||
setEditMode(true);
|
||||
if (project) {
|
||||
form.setFieldsValue({
|
||||
...project,
|
||||
start_date: project.start_date ? dayjs(project.start_date) : null,
|
||||
end_date: project.end_date ? dayjs(project.end_date) : null,
|
||||
working_days:
|
||||
form.getFieldValue('start_date') && form.getFieldValue('end_date')
|
||||
? calculateWorkingDays(
|
||||
form.getFieldValue('start_date'),
|
||||
form.getFieldValue('end_date')
|
||||
)
|
||||
: project.working_days || 0,
|
||||
use_manual_progress: project.use_manual_progress || false,
|
||||
use_weighted_progress: project.use_weighted_progress || false,
|
||||
use_time_progress: project.use_time_progress || false,
|
||||
});
|
||||
setSelectedProjectManager(project.project_manager || null);
|
||||
setLoading(false);
|
||||
}
|
||||
} else {
|
||||
console.log('Drawer visibility changed:', visible, 'Project ID:', projectId);
|
||||
setDrawerVisible(visible);
|
||||
|
||||
if (!visible) {
|
||||
resetForm();
|
||||
} else if (visible && !projectId) {
|
||||
// Creating new project - reset form immediately
|
||||
console.log('Opening drawer for new project');
|
||||
setEditMode(false);
|
||||
setLoading(false);
|
||||
} else if (visible && projectId) {
|
||||
// Editing existing project - loading state will be handled by useEffect
|
||||
console.log('Opening drawer for existing project:', projectId);
|
||||
setLoading(true);
|
||||
}
|
||||
},
|
||||
[projectId, project]
|
||||
[projectId, resetForm]
|
||||
);
|
||||
|
||||
const resetForm = useCallback(() => {
|
||||
setEditMode(false);
|
||||
form.resetFields();
|
||||
setSelectedProjectManager(null);
|
||||
}, [form]);
|
||||
|
||||
const handleDrawerClose = useCallback(() => {
|
||||
setLoading(true);
|
||||
setDrawerVisible(false);
|
||||
resetForm();
|
||||
dispatch(setProjectData({} as IProjectViewModel));
|
||||
// dispatch(setProjectId(null));
|
||||
dispatch(setDrawerProjectId(null));
|
||||
dispatch(toggleProjectDrawer());
|
||||
onClose();
|
||||
@@ -405,7 +446,7 @@ const ProjectDrawer = ({ onClose }: { onClose: () => void }) => {
|
||||
{!isEditable && (
|
||||
<Alert message={t('noPermission')} type="warning" showIcon style={{ marginBottom: 16 }} />
|
||||
)}
|
||||
<Skeleton active paragraph={{ rows: 12 }} loading={projectLoading}>
|
||||
<Skeleton active paragraph={{ rows: 12 }} loading={loading || projectLoading}>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
|
||||
Reference in New Issue
Block a user