+ );
+};
diff --git a/web/vtadmin/src/hooks/api.ts b/web/vtadmin/src/hooks/api.ts
index f3772ed4ab0..c60888ef154 100644
--- a/web/vtadmin/src/hooks/api.ts
+++ b/web/vtadmin/src/hooks/api.ts
@@ -81,6 +81,8 @@ import {
ValidateVersionShardParams,
startWorkflow,
stopWorkflow,
+ FetchTransactionsParams,
+ fetchTransactions,
} from '../api/http';
import { vtadmin as pb, vtctldata } from '../proto/vtadmin';
import { formatAlias } from '../util/tablets';
@@ -405,6 +407,16 @@ export const useVSchema = (params: FetchVSchemaParams, options?: UseQueryOptions
return useQuery(['vschema', params], () => fetchVSchema(params));
};
+/**
+ * useTransactions is a query hook that fetches unresolved transactions for the given keyspace.
+ */
+export const useTransactions = (
+ params: FetchTransactionsParams,
+ options?: UseQueryOptions | undefined
+) => {
+ return useQuery(['transactions', params], () => fetchTransactions(params), { ...options });
+};
+
export const useVTExplain = (
params: Parameters[0],
options?: UseQueryOptions | undefined
diff --git a/web/vtadmin/src/util/transactions.ts b/web/vtadmin/src/util/transactions.ts
new file mode 100644
index 00000000000..10d18cb6173
--- /dev/null
+++ b/web/vtadmin/src/util/transactions.ts
@@ -0,0 +1,28 @@
+/**
+ * Copyright 2024 The Vitess Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { invertBy } from 'lodash-es';
+import { query } from '../proto/vtadmin';
+
+/**
+ * TRANSACTION_STATES maps numeric transaction state back to human readable strings.
+ */
+export const TRANSACTION_STATES = Object.entries(invertBy(query.TransactionState)).reduce((acc, [k, vs]) => {
+ acc[k] = vs[0];
+ return acc;
+}, {} as { [k: string]: string });
+
+export const formatTransactionState = (transaction: query.ITransactionMetadata) =>
+ transaction.state && TRANSACTION_STATES[transaction.state];