Files
HiveGrid-Wireframes/hivegrid-cloud/apps/web/app/modules/helpDesk/components/FeedbackTable.tsx
T

112 lines
4.0 KiB
TypeScript

import { useSubmit, useSearchParams, useNavigation, useParams } from "react-router";
import { useState } from "react";
import { FilterablePropertyDto } from "~/application/dtos/data/FilterablePropertyDto";
import { PaginationDto } from "~/application/dtos/data/PaginationDto";
import ButtonSecondary from "~/components/ui/buttons/ButtonSecondary";
import RefreshIcon from "~/components/ui/icons/RefreshIcon";
import InputFilters from "~/components/ui/input/InputFilters";
import InputSearchWithURL from "~/components/ui/input/InputSearchWithURL";
import { FilterableValueLink } from "~/components/ui/links/FilterableValueLink";
import TableSimple from "~/components/ui/tables/TableSimple";
import { useTranslation } from "react-i18next";
import type { FeedbackWithDetails } from "../db/feedback.db.server";
import { redactFeedbackText } from "../services/FeedbackRedaction";
import { useLocaleFormatters } from "~/locale/format";
interface Props {
data: {
items: FeedbackWithDetails[];
filterableProperties: FilterablePropertyDto[];
pagination: PaginationDto;
};
}
export default function FeedbackTable({ data }: Props) {
const { t } = useTranslation();
const formatters = useLocaleFormatters();
const submit = useSubmit();
const navigation = useNavigation();
const params = useParams();
const canDelete = !params.tenant;
const [searchParams, setSearchParams] = useSearchParams();
const [selectedRows, setSelectedRows] = useState<FeedbackWithDetails[]>([]);
function onDelete(ids: string[]) {
if (!canDelete) {
return;
}
const form = new FormData();
form.set("action", "delete");
form.set("ids", ids.join(","));
submit(form, {
method: "post",
});
}
return (
<div className="space-y-2">
<div className="flex w-full items-center space-x-2">
<div className="flex-grow">
<InputSearchWithURL />
</div>
{canDelete && selectedRows.length > 0 && (
<ButtonSecondary
destructive
onClick={() => {
onDelete(selectedRows.map((x) => x.id));
setSelectedRows([]);
}}
>
{t("shared.delete")} {selectedRows.length}
</ButtonSecondary>
)}
<ButtonSecondary onClick={() => setSearchParams(searchParams)} isLoading={navigation.state === "loading"}>
<RefreshIcon className="h-4 w-4" />
</ButtonSecondary>
<InputFilters filters={data.filterableProperties} />
</div>
<TableSimple
selectedRows={canDelete ? selectedRows : undefined}
onSelected={canDelete ? setSelectedRows : undefined}
items={data.items}
pagination={data.pagination}
actions={[
{
title: t("shared.delete"),
onClick: (_, item) => onDelete([item.id]),
hidden: () => !canDelete,
disabled: () => !canDelete,
destructive: true,
},
]}
headers={[
{
name: "createdAt",
title: t("shared.createdAt"),
value: (item) => formatters.dateTime(item.createdAt, { timeStyle: "medium" }),
formattedValue: (item) => (
<div className="text-muted-foreground text-xs">{item.createdAt && <span>{formatters.dateTime(item.createdAt, { timeStyle: "medium" })}</span>}</div>
),
},
{
name: "tenant",
title: t("helpDesk.feedback.fields.tenant"),
value: (item) => <FilterableValueLink name="tenantId" value={item?.tenant?.name} param={item?.tenant?.id} />,
hidden: !!params.tenant,
},
{
name: "user",
title: t("models.user.object"),
value: (item) => <FilterableValueLink name="userId" value={item.user?.email} param={item.user?.id} />,
},
{
name: "message",
title: t("feedback.message"),
value: (item) => <div>{redactFeedbackText(item.message)}</div>,
},
]}
/>
</div>
);
}