Apply i18n to client components

This commit is contained in:
Takeshi Kimata
2024-05-03 17:39:07 +09:00
parent 72c71efedc
commit e25acad76c
8 changed files with 146 additions and 83 deletions

View File

@@ -11,13 +11,14 @@ import {
ModalBody,
ModalFooter,
} from "@nextui-org/react";
import { ProjectType } from "@/types/project";
import { ProjectType, ProjectsMessages } from "@/types/project";
type Props = {
isOpen: boolean;
editingProject: ProjectType;
onCancel: () => void;
onSubmit: (name: string, detail: string) => void;
messages: ProjectsMessages;
};
export default function ProjectDialog({
@@ -25,6 +26,7 @@ export default function ProjectDialog({
editingProject,
onCancel,
onSubmit,
messages,
}: Props) {
const [projectName, setProjectName] = useState({
text: editingProject ? editingProject.name : "",
@@ -80,7 +82,7 @@ export default function ProjectDialog({
setProjectName({
text: "",
isValid: false,
errorMessage: "Please enter project name",
errorMessage: messages.pleaseEnter,
});
return;
@@ -98,11 +100,13 @@ export default function ProjectDialog({
}}
>
<ModalContent>
<ModalHeader className="flex flex-col gap-1">Project</ModalHeader>
<ModalHeader className="flex flex-col gap-1">
{messages.project}
</ModalHeader>
<ModalBody>
<Input
type="text"
label="Project Name"
label={messages.projectName}
value={projectName.text}
isInvalid={projectName.isValid}
errorMessage={projectName.errorMessage}
@@ -114,7 +118,7 @@ export default function ProjectDialog({
}}
/>
<Textarea
label="Project Detail"
label={messages.projectDetail}
value={projectDetail.text}
isInvalid={projectDetail.isValid}
errorMessage={projectDetail.errorMessage}
@@ -128,10 +132,10 @@ export default function ProjectDialog({
</ModalBody>
<ModalFooter>
<Button variant="light" onPress={onCancel}>
Close
{messages.close}
</Button>
<Button color="primary" onPress={validate}>
{editingProject ? "Update" : "Create"}
{editingProject ? messages.update : messages.create}
</Button>
</ModalFooter>
</ModalContent>

View File

@@ -1,8 +1,8 @@
// "use client";
"use client";
import { useEffect, useState } from "react";
import { Button } from "@nextui-org/react";
import { Plus } from "lucide-react";
import { ProjectType } from "@/types/project";
import { ProjectType, ProjectsMessages } from "@/types/project";
import ProjectsTable from "./ProjectsTable";
import ProjectDialog from "./ProjectDialog";
import {
@@ -11,10 +11,12 @@ import {
updateProject,
deleteProject,
} from "./projectsControl";
import { useTranslations } from "next-intl";
export default function ProjectsPage() {
const t = useTranslations("ProjectsPage");
export type Props = {
messages: ProjectsMessages;
};
export default function ProjectsPage({ messages }: Props) {
const [projects, setProjects] = useState([]);
useEffect(() => {
@@ -78,33 +80,37 @@ export default function ProjectsPage() {
};
return (
<div className="container mx-auto max-w-3xl pt-16 px-6 flex-grow">
<div className="w-full p-3 flex items-center justify-between">
<h3 className="font-bold">{t("project.project")}</h3>
<div>
<Button
startContent={<Plus size={16} />}
size="sm"
color="primary"
onClick={openDialogForCreate}
>
{t("newProject")}
</Button>
<div className="flex justify-center">
<div className="container mx-auto max-w-3xl pt-16 px-6 flex-grow">
<div className="w-full p-3 flex items-center justify-between">
<h3 className="font-bold">{messages.project}</h3>
<div>
<Button
startContent={<Plus size={16} />}
size="sm"
color="primary"
onClick={openDialogForCreate}
>
{messages.newProject}
</Button>
</div>
</div>
<ProjectsTable
projects={projects}
onEditProject={onEditClick}
onDeleteProject={onDeleteClick}
messages={messages}
/>
<ProjectDialog
isOpen={isProjectDialogOpen}
editingProject={editingProject}
onCancel={closeDialog}
onSubmit={onSubmit}
messages={messages}
/>
</div>
<ProjectsTable
projects={projects}
onEditProject={onEditClick}
onDeleteProject={onDeleteClick}
/>
<ProjectDialog
isOpen={isProjectDialogOpen}
editingProject={editingProject}
onCancel={closeDialog}
onSubmit={onSubmit}
/>
</div>
);
}

View File

@@ -15,28 +15,30 @@ import {
Link,
} from "@nextui-org/react";
import { MoreVertical } from "lucide-react";
import { ProjectType } from "@/types/project";
import { ProjectType, ProjectsMessages } from "@/types/project";
import dayjs from "dayjs";
const headerColumns = [
{ name: "ID", uid: "id", sortable: true },
{ name: "Name", uid: "name", sortable: true },
{ name: "Detail", uid: "detail", sortable: true },
{ name: "Last update", uid: "updatedAt", sortable: true },
{ name: "Actions", uid: "actions" },
];
type Props = {
projects: ProjectType[];
onEditProject: (project: ProjectType) => void;
onDeleteProject: (projectId: number) => void;
messages: ProjectsMessages;
};
export default function ProjectsTable({
projects,
onEditProject,
onDeleteProject,
messages,
}: Props) {
const headerColumns = [
{ name: messages.id, uid: "id", sortable: true },
{ name: messages.name, uid: "name", sortable: true },
{ name: messages.detail, uid: "detail", sortable: true },
{ name: messages.lastUpdate, uid: "updatedAt", sortable: true },
{ name: messages.actions, uid: "actions" },
];
const [sortDescriptor, setSortDescriptor] = useState<SortDescriptor>({
column: "id",
direction: "ascending",
@@ -92,13 +94,13 @@ export default function ProjectsTable({
</DropdownTrigger>
<DropdownMenu aria-label="project actions">
<DropdownItem onClick={() => onEditProject(project)}>
Edit project
{messages.editProject}
</DropdownItem>
<DropdownItem
className="text-danger"
onClick={() => onDeleteProject(project.id)}
>
Delete project
{messages.deleteProject}
</DropdownItem>
</DropdownMenu>
</Dropdown>

View File

@@ -1,9 +1,29 @@
import ProjectsPage from "./ProjectsPage";
import { useTranslations } from "next-intl";
export default function Page() {
const t = useTranslations("Projects");
const messages = {
projects: t("projects"),
project: t("project"),
newProject: t("new_project"),
editProject: t("edit_project"),
deleteProject: t("delete_project"),
id: t("id"),
name: t("name"),
detail: t("detail"),
lastUpdate: t("last_update"),
actions: t("actions"),
projectName: t("project_name"),
projectDetail: t("project_detail"),
close: t("close"),
create: t("create"),
update: t("update"),
pleaseEnter: t("please_enter"),
};
return (
<>
<ProjectsPage />
<ProjectsPage messages={messages} />
</>
);
}