Phase 1C: Frontend unified contact UI

This commit is contained in:
Agent Zero
2026-07-23 17:17:32 +02:00
parent a8331fbc2b
commit 879106c4eb
62 changed files with 552 additions and 1276 deletions
+1 -1
View File
@@ -53,7 +53,7 @@ export interface CalendarEntry {
export interface CalendarEntryLink {
id: string;
entity_type: 'company' | 'contact';
entity_type: 'contact' | 'company';
entity_id: string;
}
+2 -92
View File
@@ -1,15 +1,11 @@
/**
* hooks.ts — Re-Export Hub
* hooks.ts — Re-Export Hub (Company hooks removed in Phase 1C)
*
* This file re-exports all hooks from their dedicated modules so that
* existing imports `from '@/api/hooks'` continue to work without change.
*
* Company hooks remain inline here — they will be removed in Phase 1.
*/
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { apiGet, apiPost, apiPatch, apiDelete, apiClient } from './client';
import { PaginatedResponse, Company, CompanyDetail } from './types';
import { useQuery } from '@tanstack/react-query';
// ── Re-exports from dedicated modules ──
export * from './types';
@@ -48,89 +44,3 @@ export function useGlobalSearch(query: string, entityTypes?: string[]) {
staleTime: 30 * 1000,
});
}
// ── Company hooks (will be removed in Phase 1) ──
export function useCompanies(page = 1, pageSize = 25, search?: string, industry?: string, sortBy?: string, sortOrder?: string) {
const params = new URLSearchParams({ page: String(page), page_size: String(pageSize) });
if (search) params.set('search', search);
if (industry) params.set('industry', industry);
if (sortBy) params.set('sort_by', sortBy);
if (sortOrder) params.set('sort_order', sortOrder);
return useQuery({
queryKey: ['companies', page, pageSize, search, industry, sortBy, sortOrder],
queryFn: () =>
apiGet<PaginatedResponse<Company>>(`/companies?${params.toString()}`),
});
}
export function useCompany(id?: string) {
return useQuery({
queryKey: ['companies', id],
queryFn: () => apiGet<CompanyDetail>(`/companies/${id}`),
enabled: !!id,
});
}
export function useCreateCompany() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: Partial<Company>) => apiPost('/companies', data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['companies'] });
},
});
}
export function useUpdateCompany() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, data }: { id: string; data: Partial<Company> }) =>
apiPatch(`/companies/${id}`, data),
onSuccess: (_data, variables) => {
queryClient.invalidateQueries({ queryKey: ['companies'] });
queryClient.invalidateQueries({ queryKey: ['companies', variables.id] });
},
});
}
export function useDeleteCompany() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => apiDelete(`/companies/${id}`),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['companies'] });
},
});
}
export function useCompanyExport(search?: string, industry?: string) {
return useMutation({
mutationFn: async () => {
const params = new URLSearchParams({ format: 'csv' });
if (search) params.set('search', search);
if (industry) params.set('industry', industry);
const response = await apiClient.get(`/companies/export?${params.toString()}`, {
responseType: 'blob',
});
return response.data;
},
});
}
export function useCompanyImport() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (file: File) => {
const formData = new FormData();
formData.append('file', file);
const response = await apiClient.post('/companies/import', formData, {
headers: { 'Content-Type': 'multipart/form-data' },
});
return response.data;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['companies'] });
},
});
}
-1
View File
@@ -272,7 +272,6 @@ export interface FlagUpdatePayload {
export interface LinkMailPayload {
contact_id?: string | null;
company_id?: string | null;
}
export interface CreateEventFromMailPayload {
+1 -1
View File
@@ -1,7 +1,7 @@
import { apiClient } from './client';
export interface SearchResult {
type: 'company' | 'contact' | 'mail' | 'file' | 'event';
type: 'contact' | 'mail' | 'file' | 'event';
id: string;
name: string;
description?: string;
+1 -1
View File
@@ -9,7 +9,7 @@ import { apiDelete, apiGet, apiPatch, apiPost } from './client';
// ─── Types ─────────────────────────────────────────────────────────────────
export type EntityType = 'company' | 'contact' | 'file' | 'calendar_entry';
export type EntityType = 'contact' | 'file' | 'calendar_entry';
export interface Tag {
id: string;
+1 -18
View File
@@ -9,23 +9,6 @@ export interface PaginatedResponse<T> {
page_size: number;
}
export interface Company {
id: string;
name: string;
account_number?: string | null;
industry?: string | null;
phone?: string | null;
email?: string | null;
website?: string | null;
description?: string | null;
created_at?: string;
updated_at?: string;
}
export interface CompanyDetail extends Company {
contacts?: Contact[];
}
export interface Contact {
id: string;
first_name: string;
@@ -39,5 +22,5 @@ export interface Contact {
}
export interface ContactDetail extends Contact {
companies?: Company[];
companies?: Array<{ id: string; name: string }>;
}