import { mdiChartTimelineVariant } from '@mdi/js'; import axios from 'axios'; import Head from 'next/head'; import { useRouter } from 'next/router'; import React, { ReactElement, useEffect, useState } from 'react'; import { toast, ToastContainer } from 'react-toastify'; import BaseButton from '../../components/BaseButton'; import CardBox from '../../components/CardBox'; import LayoutAuthenticated from '../../layouts/Authenticated'; import SectionMain from '../../components/SectionMain'; import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'; import { getPageTitle } from '../../config'; type ProjectItem = { id: string; name: string; slug: string; phase: string; description?: string | null; }; const ProjectsListPage = () => { const router = useRouter(); const [projects, setProjects] = useState([]); const [isLoading, setIsLoading] = useState(false); const [isCreating, setIsCreating] = useState(false); const [isCloning, setIsCloning] = useState(false); const [isCloneOpen, setIsCloneOpen] = useState(false); const [cloneSourceId, setCloneSourceId] = useState(''); const loadProjects = async () => { setIsLoading(true); try { const response = await axios.get( '/projects?limit=100&page=0&sort=desc&field=updatedAt', ); const rows = Array.isArray(response?.data?.rows) ? response.data.rows : []; setProjects(rows); if (rows.length > 0 && !cloneSourceId) { setCloneSourceId(rows[0].id); } } catch (error: any) { console.error( 'Failed to load projects list:', error?.message || 'Unknown error', ); toast('Failed to load projects', { type: 'error', position: 'bottom-center', }); } finally { setIsLoading(false); } }; useEffect(() => { loadProjects(); }, []); const buildNewProjectDraft = () => { const stamp = Date.now(); return { name: `New Project ${new Date(stamp).toISOString().slice(0, 16).replace('T', ' ')}`, slug: `project-${stamp}`, description: '', phase: 'dev', }; }; const handleOpenProjectAssets = async (projectId: string) => { await router.push(`/projects/${projectId}`); }; const handleCreateNewProject = async () => { setIsCreating(true); try { const response = await axios.post('/projects', { data: buildNewProjectDraft(), }); const createdId = response?.data?.id; if (!createdId) { throw new Error('Project was created but id is missing in response'); } await router.push(`/projects/${createdId}`); } catch (error: any) { console.error( 'Failed to create project:', error?.message || 'Unknown error', ); toast('Failed to create project', { type: 'error', position: 'bottom-center', }); } finally { setIsCreating(false); } }; const handleCloneProject = async () => { if (!cloneSourceId) { toast('Select source project first', { type: 'warning', position: 'bottom-center', }); return; } setIsCloning(true); try { const response = await axios.post(`/projects/${cloneSourceId}/clone`); const createdId = response?.data?.id; if (!createdId) { throw new Error('Cloned project id is missing in response'); } await router.push(`/projects/${createdId}`); } catch (error: any) { console.error( 'Failed to clone project:', error?.message || 'Unknown error', ); toast('Failed to clone project', { type: 'error', position: 'bottom-center', }); } finally { setIsCloning(false); } }; return ( <> {getPageTitle('Projects')} {''} setIsCloneOpen((prev) => !prev)} disabled={isCreating || isCloning || projects.length === 0} /> {isCloneOpen && (
)}
{!isLoading && projects.map((project) => ( ))} {!isLoading && projects.length === 0 && (

No projects found.

)}
); }; ProjectsListPage.getLayout = function getLayout(page: ReactElement) { return ( {page} ); }; export default ProjectsListPage;