add refresh sites button

This commit is contained in:
miloschwartz 2025-06-27 16:43:09 -04:00
parent 073c318f12
commit 809a135721
No known key found for this signature in database
5 changed files with 61 additions and 11 deletions

View file

@ -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",

View file

@ -8,12 +8,16 @@ interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
data: TData[];
createSite?: () => void;
onRefresh?: () => void;
isRefreshing?: boolean;
}
export function SitesDataTable<TData, TValue>({
columns,
data,
createSite
createSite,
onRefresh,
isRefreshing
}: DataTableProps<TData, TValue>) {
const t = useTranslations();
@ -27,6 +31,8 @@ export function SitesDataTable<TData, TValue>({
searchColumn="name"
onAdd={createSite}
addButtonText={t('siteAdd')}
onRefresh={onRefresh}
isRefreshing={isRefreshing}
defaultSort={{
id: "name",
desc: false

View file

@ -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<SiteRow | null>(null);
const [rows, setRows] = useState<SiteRow[]>(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}
/>
</>
);

View file

@ -71,7 +71,7 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
disabled={loading || props.disabled} // Disable button when loading
{...props}
>
{loading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
{/* {loading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />} */}
{props.children}
</Comp>
);

View file

@ -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<TData, TValue> = {
columns: ColumnDef<TData, TValue>[];
@ -37,6 +38,8 @@ type DataTableProps<TData, TValue> = {
title?: string;
addButtonText?: string;
onAdd?: () => void;
onRefresh?: () => void;
isRefreshing?: boolean;
searchPlaceholder?: string;
searchColumn?: string;
defaultSort?: {
@ -51,6 +54,8 @@ export function DataTable<TData, TValue>({
title,
addButtonText,
onAdd,
onRefresh,
isRefreshing,
searchPlaceholder = "Search...",
searchColumn = "name",
defaultSort
@ -60,6 +65,7 @@ export function DataTable<TData, TValue>({
);
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
const [globalFilter, setGlobalFilter] = useState<any>([]);
const t = useTranslations();
const table = useReactTable({
data,
@ -99,12 +105,25 @@ export function DataTable<TData, TValue>({
/>
<Search className="h-4 w-4 absolute left-2 top-1/2 transform -translate-y-1/2 text-muted-foreground" />
</div>
<div className="flex items-center gap-2">
{onRefresh && (
<Button
variant="outline"
onClick={onRefresh}
disabled={isRefreshing}
loading={isRefreshing}
>
<RefreshCw className={`mr-2 h-4 w-4 ${isRefreshing ? 'animate-spin' : ''}`} />
{t("refresh")}
</Button>
)}
{onAdd && addButtonText && (
<Button onClick={onAdd}>
<Plus className="mr-2 h-4 w-4" />
{addButtonText}
</Button>
)}
</div>
</CardHeader>
<CardContent>
<Table>