Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
'use client';
|
|
|
|
|
|
|
|
|
|
import { useState } from 'react';
|
|
|
|
|
import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
|
|
|
|
|
|
|
|
|
|
import { apiFetch } from '@/lib/api/client';
|
|
|
|
|
import type { SavedView } from '@/lib/db/schema/system';
|
|
|
|
|
|
|
|
|
|
export function useSavedViews(entityType: string) {
|
|
|
|
|
const queryClient = useQueryClient();
|
|
|
|
|
const [activeViewId, setActiveViewId] = useState<string | null>(null);
|
|
|
|
|
|
|
|
|
|
const queryKey = ['savedViews', entityType];
|
|
|
|
|
|
|
|
|
|
const { data: views = [] } = useQuery<SavedView[]>({
|
|
|
|
|
queryKey,
|
|
|
|
|
queryFn: () =>
|
2026-05-11 13:01:47 +02:00
|
|
|
apiFetch<{ data: SavedView[] }>(`/api/v1/saved-views?entityType=${entityType}`).then(
|
|
|
|
|
(r) => r.data,
|
|
|
|
|
),
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const saveMutation = useMutation({
|
|
|
|
|
mutationFn: (params: {
|
|
|
|
|
name: string;
|
|
|
|
|
filters: Record<string, unknown>;
|
|
|
|
|
sortConfig?: unknown;
|
|
|
|
|
}) =>
|
|
|
|
|
apiFetch<{ data: SavedView }>('/api/v1/saved-views', {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
body: { ...params, entityType },
|
|
|
|
|
}),
|
|
|
|
|
onSuccess: () => queryClient.invalidateQueries({ queryKey }),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const deleteMutation = useMutation({
|
2026-05-11 13:01:47 +02:00
|
|
|
mutationFn: (viewId: string) => apiFetch(`/api/v1/saved-views/${viewId}`, { method: 'DELETE' }),
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
onSuccess: () => queryClient.invalidateQueries({ queryKey }),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
async function saveCurrentView(
|
|
|
|
|
name: string,
|
|
|
|
|
filters: Record<string, unknown>,
|
|
|
|
|
sortConfig?: unknown,
|
|
|
|
|
) {
|
|
|
|
|
await saveMutation.mutateAsync({ name, filters, sortConfig });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function deleteView(viewId: string) {
|
|
|
|
|
if (activeViewId === viewId) setActiveViewId(null);
|
|
|
|
|
deleteMutation.mutate(viewId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function applyView(viewId: string) {
|
|
|
|
|
setActiveViewId(viewId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
views,
|
|
|
|
|
activeViewId,
|
|
|
|
|
saveCurrentView,
|
|
|
|
|
deleteView,
|
|
|
|
|
applyView,
|
|
|
|
|
};
|
|
|
|
|
}
|