From 809a1357218f5b108ad201e6110bfaf89b4cc45b Mon Sep 17 00:00:00 2001 From: miloschwartz Date: Fri, 27 Jun 2025 16:43:09 -0400 Subject: [PATCH] add refresh sites button --- messages/en-US.json | 2 ++ .../[orgId]/settings/sites/SitesDataTable.tsx | 8 ++++- src/app/[orgId]/settings/sites/SitesTable.tsx | 25 ++++++++++++- src/components/ui/button.tsx | 2 +- src/components/ui/data-table.tsx | 35 ++++++++++++++----- 5 files changed, 61 insertions(+), 11 deletions(-) diff --git a/messages/en-US.json b/messages/en-US.json index cd8f0ddb..b198caa9 100644 --- a/messages/en-US.json +++ b/messages/en-US.json @@ -776,6 +776,8 @@ "orgPoliciesAdd": "Add Organization Policy", "orgRequired": "Organization is required", "error": "Error", + "refreshError": "Failed to refresh data", + "refresh": "Refresh", "success": "Success", "orgPolicyAddedDescription": "Policy added successfully", "orgPolicyUpdatedDescription": "Policy updated successfully", diff --git a/src/app/[orgId]/settings/sites/SitesDataTable.tsx b/src/app/[orgId]/settings/sites/SitesDataTable.tsx index 99445dea..60c395c7 100644 --- a/src/app/[orgId]/settings/sites/SitesDataTable.tsx +++ b/src/app/[orgId]/settings/sites/SitesDataTable.tsx @@ -8,12 +8,16 @@ interface DataTableProps { columns: ColumnDef[]; data: TData[]; createSite?: () => void; + onRefresh?: () => void; + isRefreshing?: boolean; } export function SitesDataTable({ columns, data, - createSite + createSite, + onRefresh, + isRefreshing }: DataTableProps) { const t = useTranslations(); @@ -27,6 +31,8 @@ export function SitesDataTable({ searchColumn="name" onAdd={createSite} addButtonText={t('siteAdd')} + onRefresh={onRefresh} + isRefreshing={isRefreshing} defaultSort={{ id: "name", desc: false diff --git a/src/app/[orgId]/settings/sites/SitesTable.tsx b/src/app/[orgId]/settings/sites/SitesTable.tsx index 6aedb3eb..8b9199fa 100644 --- a/src/app/[orgId]/settings/sites/SitesTable.tsx +++ b/src/app/[orgId]/settings/sites/SitesTable.tsx @@ -19,7 +19,7 @@ import { import Link from "next/link"; import { useRouter } from "next/navigation"; import { AxiosResponse } from "axios"; -import { useState } from "react"; +import { useState, useEffect } from "react"; import CreateSiteForm from "./CreateSiteForm"; import ConfirmDeleteDialog from "@app/components/ConfirmDeleteDialog"; import { toast } from "@app/hooks/useToast"; @@ -53,10 +53,31 @@ export default function SitesTable({ sites, orgId }: SitesTableProps) { const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [selectedSite, setSelectedSite] = useState(null); const [rows, setRows] = useState(sites); + const [isRefreshing, setIsRefreshing] = useState(false); const api = createApiClient(useEnvContext()); const t = useTranslations(); + // Update local state when props change (e.g., after refresh) + useEffect(() => { + setRows(sites); + }, [sites]); + + const refreshData = async () => { + setIsRefreshing(true); + try { + router.refresh(); + } catch (error) { + toast({ + title: t("error"), + description: t("refreshError"), + variant: "destructive" + }); + } finally { + setIsRefreshing(false); + } + }; + const deleteSite = (siteId: number) => { api.delete(`/site/${siteId}`) .catch((e) => { @@ -339,6 +360,8 @@ export default function SitesTable({ sites, orgId }: SitesTableProps) { createSite={() => router.push(`/${orgId}/settings/sites/create`) } + onRefresh={refreshData} + isRefreshing={isRefreshing} /> ); diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index 55b92a6c..c6322253 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -71,7 +71,7 @@ const Button = React.forwardRef( disabled={loading || props.disabled} // Disable button when loading {...props} > - {loading && } + {/* {loading && } */} {props.children} ); diff --git a/src/components/ui/data-table.tsx b/src/components/ui/data-table.tsx index c9556052..d2577e32 100644 --- a/src/components/ui/data-table.tsx +++ b/src/components/ui/data-table.tsx @@ -23,13 +23,14 @@ import { Button } from "@app/components/ui/button"; import { useState } from "react"; import { Input } from "@app/components/ui/input"; import { DataTablePagination } from "@app/components/DataTablePagination"; -import { Plus, Search } from "lucide-react"; +import { Plus, Search, RefreshCw } from "lucide-react"; import { Card, CardContent, CardHeader, CardTitle } from "@app/components/ui/card"; +import { useTranslations } from "next-intl"; type DataTableProps = { columns: ColumnDef[]; @@ -37,6 +38,8 @@ type DataTableProps = { title?: string; addButtonText?: string; onAdd?: () => void; + onRefresh?: () => void; + isRefreshing?: boolean; searchPlaceholder?: string; searchColumn?: string; defaultSort?: { @@ -51,6 +54,8 @@ export function DataTable({ title, addButtonText, onAdd, + onRefresh, + isRefreshing, searchPlaceholder = "Search...", searchColumn = "name", defaultSort @@ -60,6 +65,7 @@ export function DataTable({ ); const [columnFilters, setColumnFilters] = useState([]); const [globalFilter, setGlobalFilter] = useState([]); + const t = useTranslations(); const table = useReactTable({ data, @@ -99,12 +105,25 @@ export function DataTable({ /> - {onAdd && addButtonText && ( - - )} +
+ {onRefresh && ( + + )} + {onAdd && addButtonText && ( + + )} +
@@ -163,4 +182,4 @@ export function DataTable({ ); -} +} \ No newline at end of file