Openstatus
www.openstatus.dev
1"use client";
2
3import { ProcessMessage } from "@/components/content/process-message";
4import { TableCellDate } from "@/components/data-table/table-cell-date";
5import { FormSheetStatusReportUpdate } from "@/components/forms/status-report-update/sheet";
6import { Button } from "@/components/ui/button";
7import {
8 Table,
9 TableBody,
10 TableCell,
11 TableHead,
12 TableHeader,
13 TableRow,
14} from "@/components/ui/table";
15import {
16 Tooltip,
17 TooltipContent,
18 TooltipProvider,
19 TooltipTrigger,
20} from "@/components/ui/tooltip";
21import { icons } from "@/data/icons";
22import { colors } from "@/data/status-report-updates.client";
23import { useTRPC } from "@/lib/trpc/client";
24import { cn } from "@/lib/utils";
25import type { RouterOutputs } from "@openstatus/api";
26import { useMutation, useQueryClient } from "@tanstack/react-query";
27import { Plus } from "lucide-react";
28import { useParams } from "next/navigation";
29import { DataTableRowActions } from "./data-table-row-actions";
30
31type StatusReportUpdates =
32 RouterOutputs["statusReport"]["list"][number]["updates"];
33
34export function DataTable({
35 updates,
36 reportId,
37}: {
38 updates: StatusReportUpdates;
39 reportId: number;
40}) {
41 const trpc = useTRPC();
42 const { id } = useParams<{ id: string }>();
43 const queryClient = useQueryClient();
44 const sendStatusReportUpdateMutation = useMutation(
45 trpc.emailRouter.sendStatusReport.mutationOptions(),
46 );
47 const createStatusReportUpdateMutation = useMutation(
48 trpc.statusReport.createStatusReportUpdate.mutationOptions({
49 onSuccess: (update) => {
50 // TODO: move to server
51 if (update?.notifySubscribers) {
52 sendStatusReportUpdateMutation.mutateAsync({ id: update.id });
53 }
54 //
55 queryClient.invalidateQueries({
56 queryKey: trpc.statusReport.list.queryKey({
57 pageId: Number.parseInt(id),
58 }),
59 });
60 queryClient.invalidateQueries({
61 queryKey: trpc.page.list.queryKey(),
62 });
63 queryClient.invalidateQueries({
64 queryKey: trpc.statusReport.list.queryKey({
65 period: "7d",
66 }),
67 });
68 },
69 }),
70 );
71
72 return (
73 <Table className="w-full">
74 <TableHeader>
75 <TableRow>
76 <TableHead className="w-7">
77 <span className="sr-only">Status</span>
78 </TableHead>
79 <TableHead>Message</TableHead>
80 <TableHead>Date</TableHead>
81 <TableHead className="w-[px]">
82 <TooltipProvider>
83 <Tooltip>
84 <FormSheetStatusReportUpdate
85 onSubmit={async (values) => {
86 await createStatusReportUpdateMutation.mutateAsync({
87 statusReportId: reportId,
88 message: values.message,
89 status: values.status,
90 date: values.date,
91 notifySubscribers: values.notifySubscribers,
92 });
93 }}
94 >
95 <TooltipTrigger asChild>
96 <Button size="icon" className="ml-auto flex h-7 w-7 p-0">
97 <Plus />
98 <span className="sr-only">Create Report Update</span>
99 </Button>
100 </TooltipTrigger>
101 </FormSheetStatusReportUpdate>
102 <TooltipContent side="left" align="center">
103 Create Report Update
104 </TooltipContent>
105 </Tooltip>
106 </TooltipProvider>
107 </TableHead>
108 </TableRow>
109 </TableHeader>
110 <TableBody>
111 {updates.map((update) => {
112 const Icon = icons.status[update.status];
113 return (
114 <TableRow key={update.id}>
115 <TableCell>
116 <div className="p-1">
117 <Icon className={cn(colors[update.status])} size={20} />
118 </div>
119 </TableCell>
120 <TableCell>
121 <div className="prose dark:prose-invert prose-sm line-clamp-3 text-wrap text-muted-foreground">
122 <ProcessMessage value={update.message} />
123 </div>
124 </TableCell>
125 <TableCell className="w-[170px] text-muted-foreground">
126 <TableCellDate value={update.date} />
127 </TableCell>
128 <TableCell className="w-8">
129 <DataTableRowActions row={update} />
130 </TableCell>
131 </TableRow>
132 );
133 })}
134 </TableBody>
135 </Table>
136 );
137}