This commit includes: - Django backend with multi-tenancy (django-tenants) - React + TypeScript frontend with Vite - Platform administration API with role-based access control - Authentication system with token-based auth - Quick login dev tools for testing different user roles - CORS and CSRF configuration for local development - Docker development environment setup 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
191 lines
5.0 KiB
TypeScript
191 lines
5.0 KiB
TypeScript
/**
|
|
* Domain Management Hooks
|
|
* React Query hooks for NameSilo domain integration
|
|
*/
|
|
|
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
import * as domainsApi from '../api/domains';
|
|
import type {
|
|
DomainAvailability,
|
|
DomainPrice,
|
|
DomainRegisterRequest,
|
|
DomainRegistration,
|
|
DomainSearchHistory,
|
|
} from '../api/domains';
|
|
|
|
// Query keys
|
|
const domainKeys = {
|
|
all: ['domains'] as const,
|
|
prices: () => [...domainKeys.all, 'prices'] as const,
|
|
registrations: () => [...domainKeys.all, 'registrations'] as const,
|
|
registration: (id: number) => [...domainKeys.registrations(), id] as const,
|
|
history: () => [...domainKeys.all, 'history'] as const,
|
|
search: (query: string, tlds: string[]) => [...domainKeys.all, 'search', query, tlds] as const,
|
|
};
|
|
|
|
// ============================================
|
|
// Search & Pricing
|
|
// ============================================
|
|
|
|
/**
|
|
* Hook to search for domain availability
|
|
*/
|
|
export const useDomainSearch = () => {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: ({ query, tlds }: { query: string; tlds?: string[] }) =>
|
|
domainsApi.searchDomains(query, tlds),
|
|
onSuccess: () => {
|
|
// Invalidate search history since new search was added
|
|
queryClient.invalidateQueries({ queryKey: domainKeys.history() });
|
|
},
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Hook to get TLD pricing
|
|
*/
|
|
export const useDomainPrices = () => {
|
|
return useQuery({
|
|
queryKey: domainKeys.prices(),
|
|
queryFn: domainsApi.getDomainPrices,
|
|
staleTime: 5 * 60 * 1000, // 5 minutes
|
|
});
|
|
};
|
|
|
|
// ============================================
|
|
// Registration
|
|
// ============================================
|
|
|
|
/**
|
|
* Hook to register a new domain
|
|
*/
|
|
export const useRegisterDomain = () => {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: (data: DomainRegisterRequest) => domainsApi.registerDomain(data),
|
|
onSuccess: () => {
|
|
// Invalidate registrations list
|
|
queryClient.invalidateQueries({ queryKey: domainKeys.registrations() });
|
|
// Also invalidate custom domains since we auto-configure
|
|
queryClient.invalidateQueries({ queryKey: ['customDomains'] });
|
|
},
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Hook to get all registered domains
|
|
*/
|
|
export const useRegisteredDomains = () => {
|
|
return useQuery({
|
|
queryKey: domainKeys.registrations(),
|
|
queryFn: domainsApi.getRegisteredDomains,
|
|
staleTime: 30 * 1000, // 30 seconds
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Hook to get a single domain registration
|
|
*/
|
|
export const useDomainRegistration = (id: number) => {
|
|
return useQuery({
|
|
queryKey: domainKeys.registration(id),
|
|
queryFn: () => domainsApi.getDomainRegistration(id),
|
|
enabled: !!id,
|
|
});
|
|
};
|
|
|
|
// ============================================
|
|
// Domain Management
|
|
// ============================================
|
|
|
|
/**
|
|
* Hook to update nameservers
|
|
*/
|
|
export const useUpdateNameservers = () => {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: ({ id, nameservers }: { id: number; nameservers: string[] }) =>
|
|
domainsApi.updateNameservers(id, nameservers),
|
|
onSuccess: (data) => {
|
|
queryClient.setQueryData(domainKeys.registration(data.id), data);
|
|
queryClient.invalidateQueries({ queryKey: domainKeys.registrations() });
|
|
},
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Hook to toggle auto-renewal
|
|
*/
|
|
export const useToggleAutoRenew = () => {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: ({ id, autoRenew }: { id: number; autoRenew: boolean }) =>
|
|
domainsApi.toggleAutoRenew(id, autoRenew),
|
|
onSuccess: (data) => {
|
|
queryClient.setQueryData(domainKeys.registration(data.id), data);
|
|
queryClient.invalidateQueries({ queryKey: domainKeys.registrations() });
|
|
},
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Hook to renew a domain
|
|
*/
|
|
export const useRenewDomain = () => {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: ({ id, years }: { id: number; years?: number }) =>
|
|
domainsApi.renewDomain(id, years),
|
|
onSuccess: (data) => {
|
|
queryClient.setQueryData(domainKeys.registration(data.id), data);
|
|
queryClient.invalidateQueries({ queryKey: domainKeys.registrations() });
|
|
},
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Hook to sync domain info from NameSilo
|
|
*/
|
|
export const useSyncDomain = () => {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: (id: number) => domainsApi.syncDomain(id),
|
|
onSuccess: (data) => {
|
|
queryClient.setQueryData(domainKeys.registration(data.id), data);
|
|
queryClient.invalidateQueries({ queryKey: domainKeys.registrations() });
|
|
},
|
|
});
|
|
};
|
|
|
|
// ============================================
|
|
// History
|
|
// ============================================
|
|
|
|
/**
|
|
* Hook to get search history
|
|
*/
|
|
export const useSearchHistory = () => {
|
|
return useQuery({
|
|
queryKey: domainKeys.history(),
|
|
queryFn: domainsApi.getSearchHistory,
|
|
staleTime: 60 * 1000, // 1 minute
|
|
});
|
|
};
|
|
|
|
// Re-export types for convenience
|
|
export type {
|
|
DomainAvailability,
|
|
DomainPrice,
|
|
DomainRegisterRequest,
|
|
DomainRegistration,
|
|
DomainSearchHistory,
|
|
RegistrantContact,
|
|
} from '../api/domains';
|