Apply i18n to client components
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
Navbar as NextUINavbar,
|
||||
NavbarContent,
|
||||
NavbarMenuToggle,
|
||||
NavbarBrand,
|
||||
NavbarItem,
|
||||
Link as NextUiLink
|
||||
@@ -36,7 +35,20 @@ export default function Header(params: { locale: string }) {
|
||||
<p className="font-bold text-inherit">Test Case Manager</p>
|
||||
</Link>
|
||||
</NavbarBrand>
|
||||
{siteConfig.navItems.map((item) => (
|
||||
<ul className="hidden lg:flex gap-4 justify-start ml-2">
|
||||
{siteConfig.navItems.map((item) => (
|
||||
<NavbarItem key={item.href}>
|
||||
<Link
|
||||
className="data-[active=true]:text-primary data-[active=true]:font-medium"
|
||||
href={item.href}
|
||||
locale={params.locale}
|
||||
>
|
||||
{item.label}
|
||||
</Link>
|
||||
</NavbarItem>
|
||||
))}
|
||||
</ul>
|
||||
{/* {siteConfig.navItems.map((item) => (
|
||||
<NavbarItem key={item.href}>
|
||||
<Link
|
||||
className="data-[active=true]:text-primary data-[active=true]:font-medium"
|
||||
@@ -46,7 +58,7 @@ export default function Header(params: { locale: string }) {
|
||||
{item.label}
|
||||
</Link>
|
||||
</NavbarItem>
|
||||
))}
|
||||
))} */}
|
||||
</NavbarContent>
|
||||
|
||||
<NavbarContent className="basis-1 pl-4" justify="end">
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user