Files
pp-tcms/frontend/src/app/[locale]/projects/[projectId]/settings/SettingsPage.tsx

175 lines
5.8 KiB
TypeScript

'use client';
import { useState, useEffect, useContext } from 'react';
import { Button, Table, TableHeader, TableColumn, TableBody, TableRow, TableCell } from '@heroui/react';
import { Pencil, Trash } from 'lucide-react';
import ProjectTagsManager from './ProjectTagsManager';
import { SettingsMessages } from '@/types/settings';
import { TokenContext } from '@/utils/TokenProvider';
import { deleteProject, fetchProject, updateProject } from '@/utils/projectsControl';
import { ProjectDialogMessages, ProjectType } from '@/types/project';
import DeleteConfirmDialog from '@/components/DeleteConfirmDialog';
import { useRouter } from '@/src/i18n/routing';
import ProjectDialog from '@/components/ProjectDialog';
import { UserType } from '@/types/user';
import { findUser } from '@/utils/usersControl';
import { logError } from '@/utils/errorHandler';
import UserAvatar from '@/components/UserAvatar';
type Props = {
projectId: string;
messages: SettingsMessages;
projectDialogMessages: ProjectDialogMessages;
locale: string;
};
export default function SettingsPage({ projectId, messages, projectDialogMessages, locale }: Props) {
const context = useContext(TokenContext);
const router = useRouter();
const [project, setProject] = useState<ProjectType>({
id: 0,
name: '',
detail: '',
isPublic: false,
userId: 0,
createdAt: '',
updatedAt: '',
Folders: [],
Runs: [],
});
const [owner, setOwner] = useState<UserType>({
id: 0,
email: '',
password: '',
avatarPath: '',
role: -1,
username: '',
locale: null,
});
useEffect(() => {
async function fetchDataEffect() {
if (!context.isSignedIn()) {
return;
}
try {
const data = await fetchProject(context.token.access_token, Number(projectId));
setProject(data);
if (data.userId) {
const ownerData = await findUser(context.token.access_token, data.userId);
setOwner(ownerData);
} else {
console.error('failed to get project owner id');
}
} catch (error: unknown) {
logError('Error fetching project data:', error);
}
}
fetchDataEffect();
}, [context, projectId]);
// project dialog
const [isProjectDialogOpen, setIsProjectDialogOpen] = useState(false);
const onSubmit = async (name: string, detail: string, isPublic: boolean) => {
const updatedProject = await updateProject(context.token.access_token, project.id, name, detail, isPublic);
setProject(updatedProject);
setIsProjectDialogOpen(false);
};
// delete confirm dialog
const [isDeleteConfirmDialogOpen, setIsDeleteConfirmDialogOpen] = useState(false);
const onConfirm = async () => {
await deleteProject(context.token.access_token, Number(projectId));
setIsDeleteConfirmDialogOpen(false);
router.push(`/projects/`, { locale: locale });
};
return (
<div className="container mx-auto max-w-3xl pt-6 px-6 flex-grow">
<div className="w-full p-3 flex items-center justify-between">
<h3 className="font-bold">{messages.projectManagement}</h3>
<div>
<Button
startContent={<Trash size={16} />}
size="sm"
color="danger"
isDisabled={!context.isProjectOwner(Number(projectId))}
onPress={() => setIsDeleteConfirmDialogOpen(true)}
>
{messages.deleteProject}
</Button>
<Button
startContent={<Pencil size={16} />}
size="sm"
color="primary"
isDisabled={!context.isProjectOwner(Number(projectId))}
onPress={() => setIsProjectDialogOpen(true)}
className="ms-2"
>
{messages.editProject}
</Button>
</div>
</div>
<div className="w-full p-3">
<Table hideHeader aria-label="Example static collection table">
<TableHeader>
<TableColumn>dummy</TableColumn>
<TableColumn>dummy</TableColumn>
</TableHeader>
<TableBody>
<TableRow key="project-name">
<TableCell>{messages.projectName}</TableCell>
<TableCell>{project.name}</TableCell>
</TableRow>
<TableRow key="project-detail">
<TableCell>{messages.projectDetail}</TableCell>
<TableCell>{project.detail}</TableCell>
</TableRow>
<TableRow key="project-owner">
<TableCell>{messages.projectOwner}</TableCell>
<TableCell>
<div className="flex gap-2 items-center">
<UserAvatar size={24} username={owner.username} avatarPath={owner.avatarPath} />
<p className="">{owner.username}</p>
</div>
</TableCell>
</TableRow>
<TableRow key="project-publicity">
<TableCell>{messages.publicity}</TableCell>
<TableCell>{project.isPublic ? messages.public : messages.private}</TableCell>
</TableRow>
</TableBody>
</Table>
</div>
<div className="w-full p-3 flex items-center justify-between">
<h3 className="font-bold">{messages.tagManagement}</h3>
</div>
<div className="w-full p-3">
<ProjectTagsManager projectId={projectId} messages={messages} />
</div>
<ProjectDialog
isOpen={isProjectDialogOpen}
editingProject={project}
onCancel={() => setIsProjectDialogOpen(false)}
onSubmit={onSubmit}
projectDialogMessages={projectDialogMessages}
/>
<DeleteConfirmDialog
isOpen={isDeleteConfirmDialogOpen}
onCancel={() => setIsDeleteConfirmDialogOpen(false)}
onConfirm={onConfirm}
closeText={messages.close}
confirmText={messages.areYouSure}
deleteText={messages.delete}
/>
</div>
);
}