11"use client" ;
22
3+ import { keepPreviousData } from "@tanstack/react-query" ;
34import { useState } from "react" ;
45
6+ import {
7+ BlockedEntriesTable ,
8+ CreateBlocklistEntryModal ,
9+ PendingReportsBadge ,
10+ PendingReportsTable ,
11+ } from "@calcom/features/blocklist" ;
12+ import { useDataTable } from "@calcom/features/data-table" ;
513import { DataTableToolbar } from "~/data-table/components" ;
614import { useLocale } from "@calcom/lib/hooks/useLocale" ;
15+ import { trpc } from "@calcom/trpc/react" ;
716import { Button } from "@calcom/ui/components/button" ;
817import { ToggleGroup } from "@calcom/ui/components/form" ;
9-
10- import PendingReportsBadge from "./components/PendingReportsBadge" ;
11- import { BlockedEntriesTable } from "./components/blocked-entries-table" ;
12- import { CreateBlocklistEntryModal } from "./components/create-blocklist-entry-modal" ;
13- import { PendingReportsTable } from "./components/pending-reports-table" ;
18+ import { showToast } from "@calcom/ui/components/toast" ;
1419
1520type ViewType = "blocked" | "pending" ;
1621
@@ -24,8 +29,86 @@ interface BlocklistTableProps {
2429
2530export function BlocklistTable ( { permissions } : BlocklistTableProps ) {
2631 const { t } = useLocale ( ) ;
32+ const { limit, offset, searchTerm } = useDataTable ( ) ;
2733 const [ activeView , setActiveView ] = useState < ViewType > ( "blocked" ) ;
2834 const [ showCreateModal , setShowCreateModal ] = useState ( false ) ;
35+ const [ selectedEntryId , setSelectedEntryId ] = useState < string | null > ( null ) ;
36+
37+ const utils = trpc . useUtils ( ) ;
38+
39+ const { data : blockedData , isPending : isBlockedPending } =
40+ trpc . viewer . organizations . listWatchlistEntries . useQuery (
41+ { limit, offset, searchTerm } ,
42+ { placeholderData : keepPreviousData , enabled : activeView === "blocked" }
43+ ) ;
44+
45+ const { data : reportsData , isPending : isReportsPending } =
46+ trpc . viewer . organizations . listBookingReports . useQuery (
47+ {
48+ limit,
49+ offset,
50+ searchTerm,
51+ filters : { hasWatchlist : false , status : [ "PENDING" ] } ,
52+ } ,
53+ { placeholderData : keepPreviousData , enabled : activeView === "pending" }
54+ ) ;
55+
56+ const { data : pendingReportsCount } =
57+ trpc . viewer . organizations . pendingReportsCount . useQuery ( ) ;
58+
59+ const { data : entryDetails , isLoading : isDetailsLoading } =
60+ trpc . viewer . organizations . getWatchlistEntryDetails . useQuery (
61+ { id : selectedEntryId ?? "" } ,
62+ { enabled : ! ! selectedEntryId }
63+ ) ;
64+
65+ const createEntry =
66+ trpc . viewer . organizations . createWatchlistEntry . useMutation ( {
67+ onSuccess : async ( ) => {
68+ await utils . viewer . organizations . listWatchlistEntries . invalidate ( ) ;
69+ showToast ( t ( "blocklist_entry_created" ) , "success" ) ;
70+ setShowCreateModal ( false ) ;
71+ } ,
72+ onError : ( error ) => {
73+ showToast ( error . message , "error" ) ;
74+ } ,
75+ } ) ;
76+
77+ const deleteEntry =
78+ trpc . viewer . organizations . deleteWatchlistEntry . useMutation ( {
79+ onSuccess : async ( ) => {
80+ await utils . viewer . organizations . listWatchlistEntries . invalidate ( ) ;
81+ setSelectedEntryId ( null ) ;
82+ showToast ( t ( "blocklist_entry_deleted" ) , "success" ) ;
83+ } ,
84+ onError : ( error ) => {
85+ showToast ( error . message , "error" ) ;
86+ } ,
87+ } ) ;
88+
89+ const addToWatchlist = trpc . viewer . organizations . addToWatchlist . useMutation ( {
90+ onSuccess : async ( ) => {
91+ await utils . viewer . organizations . listBookingReports . invalidate ( ) ;
92+ await utils . viewer . organizations . listWatchlistEntries . invalidate ( ) ;
93+ await utils . viewer . organizations . pendingReportsCount . invalidate ( ) ;
94+ showToast ( t ( "blocklist_entry_created" ) , "success" ) ;
95+ } ,
96+ onError : ( error ) => {
97+ showToast ( error . message , "error" ) ;
98+ } ,
99+ } ) ;
100+
101+ const dismissReport =
102+ trpc . viewer . organizations . dismissBookingReport . useMutation ( {
103+ onSuccess : async ( ) => {
104+ await utils . viewer . organizations . listBookingReports . invalidate ( ) ;
105+ await utils . viewer . organizations . pendingReportsCount . invalidate ( ) ;
106+ showToast ( t ( "booking_report_dismissed" ) , "success" ) ;
107+ } ,
108+ onError : ( error ) => {
109+ showToast ( error . message , "error" ) ;
110+ } ,
111+ } ) ;
29112
30113 return (
31114 < >
@@ -43,7 +126,7 @@ export function BlocklistTable({ permissions }: BlocklistTableProps) {
43126 label : (
44127 < span className = "flex items-center" >
45128 { t ( "pending" ) }
46- < PendingReportsBadge />
129+ < PendingReportsBadge count = { pendingReportsCount } />
47130 </ span >
48131 ) ,
49132 } ,
@@ -53,20 +136,58 @@ export function BlocklistTable({ permissions }: BlocklistTableProps) {
53136 </ div >
54137 < div className = "flex items-center gap-2" >
55138 { permissions ?. canCreate && (
56- < Button color = "primary" StartIcon = "plus" onClick = { ( ) => setShowCreateModal ( true ) } >
139+ < Button
140+ color = "primary"
141+ StartIcon = "plus"
142+ onClick = { ( ) => setShowCreateModal ( true ) }
143+ >
57144 { t ( "add" ) }
58145 </ Button >
59146 ) }
60147 </ div >
61148 </ div >
62149
63150 { activeView === "blocked" ? (
64- < BlockedEntriesTable permissions = { permissions } onAddClick = { ( ) => setShowCreateModal ( true ) } />
151+ < BlockedEntriesTable
152+ scope = "organization"
153+ data = { blockedData ?. rows ?? [ ] }
154+ totalRowCount = { blockedData ?. meta ?. totalRowCount ?? 0 }
155+ isPending = { isBlockedPending }
156+ limit = { limit }
157+ searchTerm = { searchTerm }
158+ permissions = { permissions }
159+ onAddClick = { ( ) => setShowCreateModal ( true ) }
160+ onDelete = { ( entry ) => deleteEntry . mutate ( { id : entry . id } ) }
161+ isDeleting = { deleteEntry . isPending }
162+ detailsQuery = { { data : entryDetails , isLoading : isDetailsLoading } }
163+ selectedEntryId = { selectedEntryId ?? undefined }
164+ onSelectEntry = { setSelectedEntryId }
165+ />
65166 ) : (
66- < PendingReportsTable />
167+ < PendingReportsTable
168+ scope = "organization"
169+ data = { reportsData ?. rows ?? [ ] }
170+ totalRowCount = { reportsData ?. meta ?. totalRowCount ?? 0 }
171+ isPending = { isReportsPending }
172+ limit = { limit }
173+ onAddToBlocklist = { ( reportIds , type , onSuccess ) =>
174+ addToWatchlist . mutate ( { reportIds, type } , { onSuccess } )
175+ }
176+ onDismiss = { ( reportId , onSuccess ) =>
177+ dismissReport . mutate ( { reportId } , { onSuccess } )
178+ }
179+ isAddingToBlocklist = { addToWatchlist . isPending }
180+ isDismissing = { dismissReport . isPending }
181+ />
67182 ) }
68183
69- < CreateBlocklistEntryModal isOpen = { showCreateModal } onClose = { ( ) => setShowCreateModal ( false ) } />
184+ < CreateBlocklistEntryModal
185+ isOpen = { showCreateModal }
186+ onClose = { ( ) => setShowCreateModal ( false ) }
187+ scope = "organization"
188+ onCreateEntry = { ( data ) => createEntry . mutate ( data ) }
189+ isPending = { createEntry . isPending }
190+ />
70191 </ >
71192 ) ;
72193}
0 commit comments