|
|
|
|
@ -1,7 +1,8 @@
|
|
|
|
|
import { useState } from "react";
|
|
|
|
|
import { Link, useNavigate } from "react-router-dom";
|
|
|
|
|
import { useNavigate } from "react-router-dom";
|
|
|
|
|
import { PROJECTS_FETCH_LIMIT } from "../../constants";
|
|
|
|
|
import ModalImport from "../modals/import";
|
|
|
|
|
import ModalNewProject from "../modals/new-project";
|
|
|
|
|
import { IProject } from "../../types";
|
|
|
|
|
import { toaster } from "../../utils";
|
|
|
|
|
import Spinner from "../../components/global/Spinner";
|
|
|
|
|
@ -17,13 +18,10 @@ const Projects = () => {
|
|
|
|
|
const [offset, setOffset] = useState(0);
|
|
|
|
|
const [importing, setImporting] = useState(false);
|
|
|
|
|
const [showImportModal, setShowImportModal] = useState(false);
|
|
|
|
|
const [showNewProjectModal, setShowNewProjectModal] = useState(false);
|
|
|
|
|
const { isLoading, isError, error, data, isFetching, isPreviousData } =
|
|
|
|
|
useProjects(limit, offset);
|
|
|
|
|
|
|
|
|
|
const onImportClick = () => {
|
|
|
|
|
setShowImportModal(true);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleImport = (values: IImportFinalValues) => {
|
|
|
|
|
setImporting(true);
|
|
|
|
|
importProject(values)
|
|
|
|
|
@ -49,10 +47,14 @@ const Projects = () => {
|
|
|
|
|
/>
|
|
|
|
|
) : null}
|
|
|
|
|
|
|
|
|
|
{showNewProjectModal ? (
|
|
|
|
|
<ModalNewProject onHide={() => setShowNewProjectModal(false)} />
|
|
|
|
|
) : null}
|
|
|
|
|
|
|
|
|
|
<div className="md:pl-16 flex flex-col flex-1 h-screen">
|
|
|
|
|
<main>
|
|
|
|
|
<div className="py-6">
|
|
|
|
|
<div className="flex flex-col sm:flex-row justify-between px-4 sm:px-6 md:px-8">
|
|
|
|
|
<div className="py-4 md:py-6">
|
|
|
|
|
<div className="flex flex-col sm:flex-row justify-between px-4 md:px-6">
|
|
|
|
|
<h1 className="text-2xl font-semibold dark:text-white text-gray-900">
|
|
|
|
|
Projects
|
|
|
|
|
</h1>
|
|
|
|
|
@ -60,26 +62,26 @@ const Projects = () => {
|
|
|
|
|
{data && data.results.length > 0 && (
|
|
|
|
|
<div className="flex justify-end space-x-1">
|
|
|
|
|
<button
|
|
|
|
|
onClick={onImportClick}
|
|
|
|
|
onClick={() => setShowImportModal(true)}
|
|
|
|
|
className="btn-util text-white bg-blue-600 hover:bg-blue-700 sm:w-auto"
|
|
|
|
|
>
|
|
|
|
|
<span>Import</span>
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
<Link
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => setShowNewProjectModal(true)}
|
|
|
|
|
className="btn-util text-white bg-blue-600 hover:bg-blue-700 sm:w-auto"
|
|
|
|
|
to="/projects/new"
|
|
|
|
|
>
|
|
|
|
|
<span>Create new project</span>
|
|
|
|
|
</Link>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="px-4 sm:px-6 md:px-8">
|
|
|
|
|
<div className="px-4 md:px-6">
|
|
|
|
|
{!isFetching && !isLoading && (
|
|
|
|
|
<>
|
|
|
|
|
<div className="py-4">
|
|
|
|
|
<div className="py-4 md:py-6">
|
|
|
|
|
{error && (
|
|
|
|
|
<div className="text-center">
|
|
|
|
|
<h3 className="mt-12 text-sm font-medium text-gray-900 dark:text-white">
|
|
|
|
|
@ -117,11 +119,17 @@ const Projects = () => {
|
|
|
|
|
Get started by creating a new project
|
|
|
|
|
</p>
|
|
|
|
|
<div className="flex flex-col md:flex-row mt-6 items-center space-y-2 md:space-y-0 space-x-2">
|
|
|
|
|
<button onClick={onImportClick} className="btn-util">
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => setShowImportModal(true)}
|
|
|
|
|
className="btn-util"
|
|
|
|
|
>
|
|
|
|
|
<span>Import</span>
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
<Link to="/projects/new" className="btn-util">
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => setShowNewProjectModal(true)}
|
|
|
|
|
className="btn-util"
|
|
|
|
|
>
|
|
|
|
|
<span className="flex space-x-1 items-center">
|
|
|
|
|
<PlusIcon
|
|
|
|
|
className="h-3 w-3"
|
|
|
|
|
@ -129,7 +137,7 @@ const Projects = () => {
|
|
|
|
|
/>
|
|
|
|
|
<span>New project</span>
|
|
|
|
|
</span>
|
|
|
|
|
</Link>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|