feat: add loading indicators for instant feedback on list updates
This commit is contained in:
@@ -4,7 +4,7 @@ import * as api from '../api/domains'
|
||||
export function useDomains() {
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
const { data: domains = [], isLoading, error } = useQuery({
|
||||
const { data: domains = [], isLoading, isFetching, error } = useQuery({
|
||||
queryKey: ['domains'],
|
||||
queryFn: api.getDomains,
|
||||
})
|
||||
@@ -26,6 +26,7 @@ export function useDomains() {
|
||||
return {
|
||||
domains,
|
||||
isLoading,
|
||||
isFetching,
|
||||
error,
|
||||
createDomain: createMutation.mutateAsync,
|
||||
deleteDomain: deleteMutation.mutateAsync,
|
||||
|
||||
@@ -42,6 +42,7 @@ export function useProxyHosts() {
|
||||
return {
|
||||
hosts: query.data || [],
|
||||
loading: query.isLoading,
|
||||
isFetching: query.isFetching,
|
||||
error: query.error ? (query.error as Error).message : null,
|
||||
createHost: createMutation.mutateAsync,
|
||||
updateHost: (uuid: string, data: Partial<ProxyHost>) => updateMutation.mutateAsync({ uuid, data }),
|
||||
|
||||
@@ -47,6 +47,7 @@ export function useRemoteServers(enabledOnly = false) {
|
||||
return {
|
||||
servers: query.data || [],
|
||||
loading: query.isLoading,
|
||||
isFetching: query.isFetching,
|
||||
error: query.error ? (query.error as Error).message : null,
|
||||
createServer: createMutation.mutateAsync,
|
||||
updateServer: (uuid: string, data: Partial<RemoteServer>) => updateMutation.mutateAsync({ uuid, data }),
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useState } from 'react'
|
||||
import { useDomains } from '../hooks/useDomains'
|
||||
import { Trash2, Plus, Globe } from 'lucide-react'
|
||||
import { Trash2, Plus, Globe, Loader2 } from 'lucide-react'
|
||||
|
||||
export default function Domains() {
|
||||
const { domains, isLoading, error, createDomain, deleteDomain } = useDomains()
|
||||
const { domains, isLoading, isFetching, error, createDomain, deleteDomain } = useDomains()
|
||||
const [newDomain, setNewDomain] = useState('')
|
||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||
|
||||
@@ -38,7 +38,10 @@ export default function Domains() {
|
||||
return (
|
||||
<div className="p-8">
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<h1 className="text-3xl font-bold text-white">Domains</h1>
|
||||
<div className="flex items-center gap-3">
|
||||
<h1 className="text-3xl font-bold text-white">Domains</h1>
|
||||
{isFetching && !isLoading && <Loader2 className="animate-spin text-blue-400" size={24} />}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { useState } from 'react'
|
||||
import { Loader2 } from 'lucide-react'
|
||||
import { useProxyHosts } from '../hooks/useProxyHosts'
|
||||
import type { ProxyHost } from '../api/proxyHosts'
|
||||
import ProxyHostForm from '../components/ProxyHostForm'
|
||||
import { Switch } from '../components/ui/Switch'
|
||||
|
||||
export default function ProxyHosts() {
|
||||
const { hosts, loading, error, createHost, updateHost, deleteHost } = useProxyHosts()
|
||||
const { hosts, loading, isFetching, error, createHost, updateHost, deleteHost } = useProxyHosts()
|
||||
const [showForm, setShowForm] = useState(false)
|
||||
const [editingHost, setEditingHost] = useState<ProxyHost | undefined>()
|
||||
|
||||
@@ -42,7 +43,10 @@ export default function ProxyHosts() {
|
||||
return (
|
||||
<div className="p-8">
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<h1 className="text-3xl font-bold text-white">Proxy Hosts</h1>
|
||||
<div className="flex items-center gap-3">
|
||||
<h1 className="text-3xl font-bold text-white">Proxy Hosts</h1>
|
||||
{isFetching && !loading && <Loader2 className="animate-spin text-blue-400" size={24} />}
|
||||
</div>
|
||||
<button
|
||||
onClick={handleAdd}
|
||||
className="px-4 py-2 bg-blue-active hover:bg-blue-hover text-white rounded-lg font-medium transition-colors"
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { useState } from 'react'
|
||||
import { Loader2 } from 'lucide-react'
|
||||
import { useRemoteServers } from '../hooks/useRemoteServers'
|
||||
import type { RemoteServer } from '../api/remoteServers'
|
||||
import RemoteServerForm from '../components/RemoteServerForm'
|
||||
|
||||
export default function RemoteServers() {
|
||||
const { servers, loading, error, createServer, updateServer, deleteServer } = useRemoteServers()
|
||||
const { servers, loading, isFetching, error, createServer, updateServer, deleteServer } = useRemoteServers()
|
||||
const [showForm, setShowForm] = useState(false)
|
||||
const [editingServer, setEditingServer] = useState<RemoteServer | undefined>()
|
||||
const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid')
|
||||
@@ -42,7 +43,10 @@ export default function RemoteServers() {
|
||||
return (
|
||||
<div className="p-8">
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<h1 className="text-3xl font-bold text-white">Remote Servers</h1>
|
||||
<div className="flex items-center gap-3">
|
||||
<h1 className="text-3xl font-bold text-white">Remote Servers</h1>
|
||||
{isFetching && !loading && <Loader2 className="animate-spin text-blue-400" size={24} />}
|
||||
</div>
|
||||
<div className="flex gap-3">
|
||||
<div className="flex bg-gray-800 rounded-lg p-1">
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user