Fix project list empty (#335)

* Move all fetch project actions to layout

* fixup! Move all fetch project actions to layout
This commit is contained in:
Chris 2025-09-16 12:07:57 +03:00 committed by antanst
parent a336653e23
commit 17cba48ef8
6 changed files with 45 additions and 86 deletions

View file

@ -89,8 +89,20 @@ const Layout: React.FC<LayoutProps> = ({
}, []);
useEffect(() => {
// Layout no longer loads global data
}, []);
// Load projects into global store if not already loaded
const loadProjects = async () => {
if (projects.length === 0 && !isProjectsLoading) {
try {
const projectsData = await fetchProjects();
setProjects(projectsData);
} catch (error) {
console.error('Failed to load projects in Layout:', error);
}
}
};
loadProjects();
}, [projects.length, isProjectsLoading, setProjects]);
const openNoteModal = (note: Note | null = null) => {
setSelectedNote(note);

View file

@ -15,8 +15,8 @@ import {
deleteNote as apiDeleteNote,
updateNote as apiUpdateNote,
} from '../../utils/notesService';
import { createProject, fetchProjects } from '../../utils/projectsService';
import { Project } from '../../entities/Project';
import { createProject } from '../../utils/projectsService';
import { useStore } from '../../store/useStore';
const NoteDetails: React.FC = () => {
const { uidSlug } = useParams<{ uidSlug: string }>();
@ -27,7 +27,8 @@ const NoteDetails: React.FC = () => {
const [noteToDelete, setNoteToDelete] = useState<Note | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [isError, setIsError] = useState(false);
const [projects, setProjects] = useState<Project[]>([]);
const projects = useStore((state: any) => state.projectsStore.projects);
const { setProjects } = useStore((state: any) => state.projectsStore);
const navigate = useNavigate();
// Dispatch global modal events
@ -51,18 +52,7 @@ const NoteDetails: React.FC = () => {
fetchNote();
}, [uidSlug]);
// Load projects for the modal
useEffect(() => {
const loadProjects = async () => {
try {
const fetchedProjects = await fetchProjects('all', '');
setProjects(fetchedProjects);
} catch (error) {
console.error('Error loading projects:', error);
}
};
loadProjects();
}, []);
// Projects are now loaded by Layout component into global store
const handleDeleteNote = async () => {
if (!noteToDelete) return;
@ -101,7 +91,7 @@ const NoteDetails: React.FC = () => {
name,
priority: 'low',
});
setProjects((prev) => [...prev, newProject]);
setProjects([...projects, newProject]);
return newProject;
} catch (error) {
console.error('Error creating project:', error);

View file

@ -12,7 +12,7 @@ import {
deleteNote as apiDeleteNote,
} from '../utils/notesService';
import { useStore } from '../store/useStore';
import { createProject, fetchProjects } from '../utils/projectsService';
import { createProject } from '../utils/projectsService';
const Notes: React.FC = () => {
const { t } = useTranslation();
@ -28,7 +28,6 @@ const Notes: React.FC = () => {
const { notes, isLoading, isError, hasLoaded, loadNotes, setNotes } =
useStore((state) => state.notesStore);
const projects = useStore((state) => state.projectsStore.projects);
const { setProjects } = useStore((state) => state.projectsStore);
useEffect(() => {
if (!hasLoaded && !isLoading && !isError) {
@ -36,20 +35,7 @@ const Notes: React.FC = () => {
}
}, [hasLoaded, isLoading, isError, loadNotes]);
// Load projects if not available - force load every time for debugging
useEffect(() => {
const loadProjectsIfNeeded = async () => {
try {
// Fetch all projects (active and inactive)
const fetchedProjects = await fetchProjects('all', '');
setProjects(fetchedProjects);
} catch (error) {
console.error('Error loading projects:', error);
}
};
loadProjectsIfNeeded();
}, []); // Remove dependencies to force it to run once
// Projects are now loaded by Layout component into global store
// Sort options for notes
const sortOptions: SortOption[] = [

View file

@ -118,19 +118,7 @@ const Projects: React.FC = () => {
loadAreas();
}, []);
useEffect(() => {
const loadProjects = async () => {
try {
const projectsData = await fetchProjects();
setProjects(projectsData);
} catch (error) {
console.error('Failed to fetch projects:', error);
setProjectsError(true);
}
};
loadProjects();
}, []);
// Projects are now loaded by Layout component into global store
// Modal state tracking removed after fixing the issue

View file

@ -16,6 +16,7 @@ import TaskList from '../Task/TaskList';
import ProjectItem from '../Project/ProjectItem';
import { Tag } from '../../entities/Tag';
import { useStore } from '../../store/useStore';
const TagDetails: React.FC = () => {
const { t } = useTranslation();
@ -23,10 +24,19 @@ const TagDetails: React.FC = () => {
const [tag, setTag] = useState<Tag | null>(null);
const [tasks, setTasks] = useState<Task[]>([]);
const [notes, setNotes] = useState<Note[]>([]);
const [projects, setProjects] = useState<Project[]>([]);
const allProjects = useStore((state: any) => state.projectsStore.projects);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
// Filter projects by current tag
const projects = allProjects.filter(
(project: any) =>
project.tags &&
project.tags.some(
(projectTag: any) => projectTag.name === tag?.name
)
);
// State for ProjectItem components
const [activeDropdown, setActiveDropdown] = useState<number | null>(null);
const [hoveredNoteId, setHoveredNoteId] = useState<number | null>(null);
@ -45,16 +55,10 @@ const TagDetails: React.FC = () => {
setTag(tagData);
// Now fetch entities that have this tag using the tag name
const [tasksResponse, notesResponse, projectsResponse] =
await Promise.all([
fetch(
`/api/tasks?tag=${encodeURIComponent(tagData.name)}`
),
fetch(
`/api/notes?tag=${encodeURIComponent(tagData.name)}`
),
fetch(`/api/projects`), // Projects API doesn't support tag filtering yet
]);
const [tasksResponse, notesResponse] = await Promise.all([
fetch(`/api/tasks?tag=${encodeURIComponent(tagData.name)}`),
fetch(`/api/notes?tag=${encodeURIComponent(tagData.name)}`),
]);
if (tasksResponse.ok) {
const tasksData = await tasksResponse.json();
@ -66,20 +70,7 @@ const TagDetails: React.FC = () => {
setNotes(notesData || []);
}
if (projectsResponse.ok) {
const projectsData = await projectsResponse.json();
// Filter projects client-side since API doesn't support tag filtering
const allProjects =
projectsData.projects || projectsData || [];
const filteredProjects = allProjects.filter(
(project: any) =>
project.tags &&
project.tags.some(
(tag: any) => tag.name === tagData.name
)
);
setProjects(filteredProjects);
}
// Projects are now filtered from global store
} catch {
setError(t('tags.error'));
} finally {

View file

@ -7,7 +7,6 @@ import GroupedTaskList from './Task/GroupedTaskList';
import NewTask from './Task/NewTask';
import SortFilter from './Shared/SortFilter';
import { Task } from '../entities/Task';
import { Project } from '../entities/Project';
import { getTitleAndIcon } from './Task/getTitleAndIcon';
import { getDescription } from './Task/getDescription';
import {
@ -15,6 +14,7 @@ import {
toggleTaskToday,
GroupedTasks,
} from '../utils/tasksService';
import { useStore } from '../store/useStore';
import { useToast } from './Shared/ToastContext';
import { SortOption } from './Shared/SortFilterButton';
import {
@ -44,7 +44,7 @@ const Tasks: React.FC = () => {
const { showSuccessToast } = useToast();
const { isSidebarOpen } = useSidebar();
const [tasks, setTasks] = useState<Task[]>([]);
const [projects, setProjects] = useState<Project[]>([]);
const projects = useStore((state: any) => state.projectsStore.projects);
const [groupedTasks, setGroupedTasks] = useState<GroupedTasks | null>(null);
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
@ -184,12 +184,9 @@ const Tasks: React.FC = () => {
const searchParams = allTasksUrl.toString();
const [tasksResponse, projectsResponse] = await Promise.all([
fetch(
`/api/tasks?${searchParams}${tagId ? `&tag=${tagId}` : ''}`
),
fetch('/api/projects'),
]);
const tasksResponse = await fetch(
`/api/tasks?${searchParams}${tagId ? `&tag=${tagId}` : ''}`
);
if (tasksResponse.ok) {
const tasksData = await tasksResponse.json();
@ -199,12 +196,7 @@ const Tasks: React.FC = () => {
throw new Error('Failed to fetch tasks.');
}
if (projectsResponse.ok) {
const projectsData = await projectsResponse.json();
setProjects(projectsData?.projects || []);
} else {
throw new Error('Failed to fetch projects.');
}
// Projects are now loaded by Layout component into global store
} catch (error) {
setError((error as Error).message);
} finally {