create project dialog

This commit is contained in:
Takeshi Kimata
2024-02-18 15:31:38 +09:00
parent a44c50df29
commit 4586c84b4e
2 changed files with 152 additions and 99 deletions

View File

@@ -2,20 +2,20 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { title } from "@/components/primitives"; import { title } from "@/components/primitives";
import { ProjectCard } from "./project-card"; import { ProjectCard } from "./project-card";
import { import { ProjectDialog } from "./project-dialog";
Button, import { Button } from "@nextui-org/react";
Input,
Textarea,
Modal,
ModalContent,
ModalHeader,
ModalBody,
ModalFooter,
} from "@nextui-org/react";
import Config from "@/config/config"; import Config from "@/config/config";
const apiServer = Config.apiServer; const apiServer = Config.apiServer;
export type ProjectType = {
id: number;
name: string;
detail: string;
createdAt: string;
updatedAt: string;
};
/** /**
* fetch project records * fetch project records
* *
@@ -23,7 +23,7 @@ const apiServer = Config.apiServer;
* @returns {Promise<Array>} - project record array * @returns {Promise<Array>} - project record array
* @throws {Error} * @throws {Error}
*/ */
async function fetchProjects(url) { async function fetchProjects(url: string) {
try { try {
const response = await fetch(url, { const response = await fetch(url, {
method: "GET", method: "GET",
@@ -50,7 +50,7 @@ async function fetchProjects(url) {
* @function * @function
* @throws {Error} * @throws {Error}
*/ */
async function createProject(name, detail) { async function createProject(name: string, detail: string) {
const newProjectData = { const newProjectData = {
name: name, name: name,
detail: detail, detail: detail,
@@ -118,51 +118,23 @@ export default function ProjectsPage() {
fetchDataEffect(); fetchDataEffect();
}, []); }, []);
// new project data // dialog
const [projectName, setProjectName] = useState({ const [isProjectDialogOpen, setIsProjectDialogOpen] = useState(false);
text: "", const [editingProject, setEditingProject] = useState(null);
isValid: false, const openDialogForCreate = () => {
errorMessage: "", setIsProjectDialogOpen(true);
}); setEditingProject(null);
const [projectDetail, setProjectDetail] = useState({
text: "",
isValid: false,
errorMessage: "",
});
// modal
const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);
const openModal = () => {
setIsCreateDialogOpen(true);
}; };
const closeModal = () => { const closeDialog = () => {
setProjectName({ text: "", isValid: false, errorMessage: "" }); setIsProjectDialogOpen(false);
setProjectDetail({ text: "", isValid: false, errorMessage: "" }); setEditingProject(null);
setIsCreateDialogOpen(false);
}; };
const onCreateClicked = async () => { const onSubmit = async (name: string, detail: string) => {
let isValid = true; const newProject = await createProject(name, detail);
setProjects([...projects, newProject]);
// validate projectName closeDialog();
if (!projectName.text) {
setProjectName({
text: "",
isValid: false,
errorMessage: "Please enter project name",
});
isValid = false;
}
if (isValid) {
const newProject = await createProject(
projectName.text,
projectDetail.text
);
setProjects([...projects, newProject]);
closeModal();
}
}; };
const onDeleteClicked = async (projectId: number) => { const onDeleteClicked = async (projectId: number) => {
@@ -178,7 +150,11 @@ export default function ProjectsPage() {
<div className="container mx-auto max-w-7xl pt-16 px-6 flex-grow"> <div className="container mx-auto max-w-7xl pt-16 px-6 flex-grow">
<div className="flex h-full items-center"> <div className="flex h-full items-center">
<h1 className={title()}>Projects</h1> <h1 className={title()}>Projects</h1>
<Button color="primary" onClick={openModal} className="ms-5 mt-3"> <Button
color="primary"
onClick={openDialogForCreate}
className="ms-5 mt-3"
>
Create Create
</Button> </Button>
</div> </div>
@@ -193,51 +169,12 @@ export default function ProjectsPage() {
))} ))}
</div> </div>
<Modal <ProjectDialog
isOpen={isCreateDialogOpen} isOpen={isProjectDialogOpen}
onOpenChange={() => { project={editingProject}
setIsCreateDialogOpen(false); onCancel={closeDialog}
}} onSubmit={onSubmit}
> />
<ModalContent>
<ModalHeader className="flex flex-col gap-1">Project</ModalHeader>
<ModalBody>
<Input
type="text"
label="Project Name"
value={projectName.text}
isInvalid={projectName.isValid}
errorMessage={projectName.errorMessage}
onChange={(e) => {
setProjectName({
...projectName,
text: e.target.value,
});
}}
/>
<Textarea
label="Project Detail"
value={projectDetail.text}
isInvalid={projectDetail.isValid}
errorMessage={projectDetail.errorMessage}
onChange={(e) => {
setProjectDetail({
...projectDetail,
text: e.target.value,
});
}}
/>
</ModalBody>
<ModalFooter>
<Button variant="light" onPress={closeModal}>
Close
</Button>
<Button color="primary" onPress={onCreateClicked}>
Create
</Button>
</ModalFooter>
</ModalContent>
</Modal>
</div> </div>
); );
} }

View File

@@ -0,0 +1,116 @@
"use client";
import React from "react";
import { useState } from "react";
import {
Button,
Input,
Textarea,
Modal,
ModalContent,
ModalHeader,
ModalBody,
ModalFooter,
} from "@nextui-org/react";
import { ProjectType } from "./page";
type Props = {
isOpen: boolean;
editingProject: ProjectType;
onCancel: () => void;
onSubmit: (name: string, detail: string) => void;
};
export function ProjectDialog({
isOpen,
editingProject,
onCancel,
onSubmit,
}: Props) {
const [projectName, setProjectName] = useState({
text: editingProject ? editingProject.name : "",
isValid: false,
errorMessage: "",
});
const [projectDetail, setProjectDetail] = useState({
text: editingProject ? editingProject.detail : "",
isValid: false,
errorMessage: "",
});
const clear = () => {
setProjectName({
isValid: false,
text: "",
errorMessage: "",
});
setProjectDetail({
isValid: false,
text: "",
errorMessage: "",
});
};
const validate = () => {
if (!projectName.text) {
setProjectName({
text: "",
isValid: false,
errorMessage: "Please enter project name",
});
return;
}
onSubmit(projectName.text, projectDetail.text);
clear();
};
return (
<Modal
isOpen={isOpen}
onOpenChange={() => {
onCancel();
}}
>
<ModalContent>
<ModalHeader className="flex flex-col gap-1">Project</ModalHeader>
<ModalBody>
<Input
type="text"
label="Project Name"
value={projectName.text}
isInvalid={projectName.isValid}
errorMessage={projectName.errorMessage}
onChange={(e) => {
setProjectName({
...projectName,
text: e.target.value,
});
}}
/>
<Textarea
label="Project Detail"
value={projectDetail.text}
isInvalid={projectDetail.isValid}
errorMessage={projectDetail.errorMessage}
onChange={(e) => {
setProjectDetail({
...projectDetail,
text: e.target.value,
});
}}
/>
</ModalBody>
<ModalFooter>
<Button variant="light" onPress={onCancel}>
Close
</Button>
<Button color="primary" onPress={validate}>
{editingProject ? "Update" : "Create"}
</Button>
</ModalFooter>
</ModalContent>
</Modal>
);
}