151 lines
4.6 KiB
TypeScript
151 lines
4.6 KiB
TypeScript
import {
|
|
AppRouterOutput,
|
|
defaultErrorHandler,
|
|
defaultSuccessHandler,
|
|
trpc,
|
|
} from '@/api/trpc';
|
|
import { CommonHeader } from '@/components/CommonHeader';
|
|
import { CommonWrapper } from '@/components/CommonWrapper';
|
|
import { ScrollArea, ScrollBar } from '@/components/ui/scroll-area';
|
|
import { useCurrentWorkspaceId } from '@/store/user';
|
|
import { routeAuthBeforeLoad } from '@/utils/route';
|
|
import { useTranslation } from '@i18next-toolkit/react';
|
|
import { createFileRoute, useNavigate } from '@tanstack/react-router';
|
|
import { useEvent } from '@/hooks/useEvent';
|
|
import { AlertConfirm } from '@/components/AlertConfirm';
|
|
import { LuPencil, LuTrash } from 'react-icons/lu';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
import { DataTable, createColumnHelper } from '@/components/DataTable';
|
|
import { useMemo } from 'react';
|
|
import { SurveyDownloadBtn } from '@/components/survey/SurveyDownloadBtn';
|
|
import dayjs from 'dayjs';
|
|
import { SurveyUsageBtn } from '@/components/survey/SurveyUsageBtn';
|
|
import { Scrollbar } from '@radix-ui/react-scroll-area';
|
|
|
|
type SurveyResultItem =
|
|
AppRouterOutput['survey']['resultList']['items'][number];
|
|
|
|
const columnHelper = createColumnHelper<SurveyResultItem>();
|
|
|
|
export const Route = createFileRoute('/survey/$surveyId/')({
|
|
beforeLoad: routeAuthBeforeLoad,
|
|
component: PageComponent,
|
|
});
|
|
|
|
function PageComponent() {
|
|
const { surveyId } = Route.useParams<{ surveyId: string }>();
|
|
const workspaceId = useCurrentWorkspaceId();
|
|
const { t } = useTranslation();
|
|
const { data: info } = trpc.survey.get.useQuery({
|
|
workspaceId,
|
|
surveyId,
|
|
});
|
|
const { data: count } = trpc.survey.count.useQuery({
|
|
workspaceId,
|
|
surveyId,
|
|
});
|
|
const { data: resultList } = trpc.survey.resultList.useInfiniteQuery({
|
|
workspaceId,
|
|
surveyId,
|
|
});
|
|
const deleteMutation = trpc.survey.delete.useMutation({
|
|
onSuccess: defaultSuccessHandler,
|
|
onError: defaultErrorHandler,
|
|
});
|
|
const trpcUtils = trpc.useUtils();
|
|
const navigate = useNavigate();
|
|
|
|
const handleDelete = useEvent(async () => {
|
|
await deleteMutation.mutateAsync({ workspaceId, surveyId });
|
|
trpcUtils.survey.all.refetch();
|
|
navigate({
|
|
to: '/survey',
|
|
replace: true,
|
|
});
|
|
});
|
|
|
|
const dataSource = resultList?.pages.map((p) => p.items).flat() ?? [];
|
|
|
|
const columns = useMemo(() => {
|
|
return [
|
|
columnHelper.accessor('id', {
|
|
header: t('ID'),
|
|
size: 150,
|
|
}),
|
|
...(info?.payload.items.map((item) =>
|
|
columnHelper.accessor(`payload.${item.name}`, {
|
|
header: item.label,
|
|
})
|
|
) ?? []),
|
|
columnHelper.accessor('createdAt', {
|
|
header: t('Created At'),
|
|
size: 130,
|
|
cell: (props) => dayjs(props.getValue()).format('YYYY-MM-DD HH:mm:ss'),
|
|
}),
|
|
];
|
|
}, [t, info]);
|
|
|
|
return (
|
|
<CommonWrapper
|
|
header={
|
|
<CommonHeader
|
|
title={info?.name ?? ''}
|
|
actions={
|
|
<div className="space-x-2">
|
|
<Button
|
|
variant="outline"
|
|
size="icon"
|
|
Icon={LuPencil}
|
|
onClick={() =>
|
|
navigate({
|
|
to: '/survey/$surveyId/edit',
|
|
params: {
|
|
surveyId,
|
|
},
|
|
})
|
|
}
|
|
/>
|
|
|
|
<AlertConfirm
|
|
title={t('Confirm to delete this survey?')}
|
|
description={t('Survey name: {{name}} | data count: {{num}}', {
|
|
name: info?.name ?? '',
|
|
num: count ?? 0,
|
|
})}
|
|
content={t('It will permanently delete the relevant data')}
|
|
onConfirm={handleDelete}
|
|
>
|
|
<Button variant="outline" size="icon" Icon={LuTrash} />
|
|
</AlertConfirm>
|
|
</div>
|
|
}
|
|
/>
|
|
}
|
|
>
|
|
<div className="h-full overflow-hidden p-4">
|
|
<div className="mb-4 w-full">
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>{t('Count')}</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="flex justify-between">
|
|
<div>{count}</div>
|
|
<div className="flex gap-2">
|
|
<SurveyUsageBtn surveyId={surveyId} />
|
|
<SurveyDownloadBtn surveyId={surveyId} />
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
<ScrollArea className="w-full">
|
|
<Scrollbar orientation="horizontal" />
|
|
|
|
<DataTable columns={columns} data={dataSource} />
|
|
</ScrollArea>
|
|
</div>
|
|
</CommonWrapper>
|
|
);
|
|
}
|