feat: standardize correspondent and tag types with usage count
This commit is contained in:
@@ -1,22 +1,11 @@
|
|||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
import type { FormEvent, KeyboardEvent } from 'react';
|
import type { FormEvent, KeyboardEvent } from 'react';
|
||||||
|
import type { Correspondent } from '../types/documents';
|
||||||
interface CorrespondentUsage {
|
|
||||||
total?: number;
|
|
||||||
[key: string]: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface CorrespondentEntry {
|
|
||||||
id?: string;
|
|
||||||
name?: string;
|
|
||||||
usage?: CorrespondentUsage;
|
|
||||||
[key: string]: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CorrespondentsPanelProps {
|
export interface CorrespondentsPanelProps {
|
||||||
correspondents?: CorrespondentEntry[];
|
correspondents?: Correspondent[];
|
||||||
onRefresh?: () => void | Promise<void>;
|
onRefresh?: () => void | Promise<void>;
|
||||||
onCreate: (payload: { name: string }) => Promise<CorrespondentEntry | void>;
|
onCreate: (payload: { name: string }) => Promise<Correspondent | void>;
|
||||||
onUpdate: (id: string, payload: { name: string }) => Promise<void>;
|
onUpdate: (id: string, payload: { name: string }) => Promise<void>;
|
||||||
onDelete: (id: string) => Promise<void>;
|
onDelete: (id: string) => Promise<void>;
|
||||||
onNotify?: (message: string, variant?: string) => void;
|
onNotify?: (message: string, variant?: string) => void;
|
||||||
@@ -37,7 +26,7 @@ function CorrespondentsPanel({
|
|||||||
const [creating, setCreating] = useState(false);
|
const [creating, setCreating] = useState(false);
|
||||||
const [deletingId, setDeletingId] = useState<string | null>(null);
|
const [deletingId, setDeletingId] = useState<string | null>(null);
|
||||||
|
|
||||||
const startEdit = useCallback((correspondent: CorrespondentEntry) => {
|
const startEdit = useCallback((correspondent: Correspondent) => {
|
||||||
setEditingId(correspondent.id);
|
setEditingId(correspondent.id);
|
||||||
setDraftName(correspondent.name);
|
setDraftName(correspondent.name);
|
||||||
}, []);
|
}, []);
|
||||||
@@ -68,7 +57,7 @@ function CorrespondentsPanel({
|
|||||||
}, [editingId, draftName, onUpdate, cancelEdit, onNotify]);
|
}, [editingId, draftName, onUpdate, cancelEdit, onNotify]);
|
||||||
|
|
||||||
const handleDelete = useCallback(
|
const handleDelete = useCallback(
|
||||||
async (correspondent: CorrespondentEntry) => {
|
async (correspondent: Correspondent) => {
|
||||||
if (!correspondent?.id) return;
|
if (!correspondent?.id) return;
|
||||||
setDeletingId(correspondent.id);
|
setDeletingId(correspondent.id);
|
||||||
try {
|
try {
|
||||||
@@ -121,12 +110,12 @@ function CorrespondentsPanel({
|
|||||||
[handleSave, cancelEdit],
|
[handleSave, cancelEdit],
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderUsage = useCallback((usage?: CorrespondentUsage) => {
|
const renderUsage = useCallback((correspondent: Correspondent) => {
|
||||||
if (!usage) {
|
const count = correspondent.usage_count;
|
||||||
|
if (count == null || !Number.isFinite(count)) {
|
||||||
return '0';
|
return '0';
|
||||||
}
|
}
|
||||||
const total = Number.isFinite(usage.total) ? Number(usage.total) : 0;
|
return count.toString();
|
||||||
return total.toString();
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -195,7 +184,7 @@ function CorrespondentsPanel({
|
|||||||
<span>{correspondent.name}</span>
|
<span>{correspondent.name}</span>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
<td className="numeric">{renderUsage(correspondent.usage)}</td>
|
<td className="numeric">{renderUsage(correspondent)}</td>
|
||||||
<td className="actions">
|
<td className="actions">
|
||||||
{isEditing ? (
|
{isEditing ? (
|
||||||
<div className="tags-table__edit-controls">
|
<div className="tags-table__edit-controls">
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { MutableRefObject, useCallback, useState } from 'react';
|
import { MutableRefObject, useCallback, useState } from 'react';
|
||||||
|
import type { Correspondent } from '../../types/documents';
|
||||||
|
|
||||||
type ApiClient = {
|
type ApiClient = {
|
||||||
get: (path: string) => Promise<{ data: unknown }>;
|
get: (path: string) => Promise<{ data: unknown }>;
|
||||||
@@ -7,12 +8,6 @@ type ApiClient = {
|
|||||||
delete: (path: string) => Promise<{ data: unknown }>;
|
delete: (path: string) => Promise<{ data: unknown }>;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface CorrespondentEntry {
|
|
||||||
id?: string;
|
|
||||||
name?: string;
|
|
||||||
[key: string]: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface UseCorrespondentsOptions {
|
interface UseCorrespondentsOptions {
|
||||||
apiClient: ApiClient;
|
apiClient: ApiClient;
|
||||||
notifyApiError: (error: unknown, fallback: string) => void;
|
notifyApiError: (error: unknown, fallback: string) => void;
|
||||||
@@ -28,7 +23,7 @@ const useCorrespondents = ({
|
|||||||
tenantIdRef,
|
tenantIdRef,
|
||||||
mapDocumentCaches,
|
mapDocumentCaches,
|
||||||
}: UseCorrespondentsOptions) => {
|
}: UseCorrespondentsOptions) => {
|
||||||
const [correspondents, setCorrespondents] = useState<CorrespondentEntry[]>([]);
|
const [correspondents, setCorrespondents] = useState<Correspondent[]>([]);
|
||||||
|
|
||||||
const refreshCorrespondents = useCallback(async () => {
|
const refreshCorrespondents = useCallback(async () => {
|
||||||
const requestTenantId = tenantIdRef.current;
|
const requestTenantId = tenantIdRef.current;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { MutableRefObject, useCallback, useState } from 'react';
|
import { MutableRefObject, useCallback, useState } from 'react';
|
||||||
import type { TagId, TenantId } from '../../types/identifiers';
|
import type { TagId, TenantId } from '../../types/identifiers';
|
||||||
|
import type { Tag } from '../../types/documents';
|
||||||
|
|
||||||
type ApiClient = {
|
type ApiClient = {
|
||||||
get: (path: string) => Promise<{ data: unknown }>
|
get: (path: string) => Promise<{ data: unknown }>
|
||||||
@@ -12,13 +13,6 @@ interface TagManagerInterface {
|
|||||||
buildPayload: (input: { label?: string; color?: string | null }) => { label: string; color: string | null };
|
buildPayload: (input: { label?: string; color?: string | null }) => { label: string; color: string | null };
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TagEntry {
|
|
||||||
id?: TagId;
|
|
||||||
label?: string;
|
|
||||||
color?: string | null;
|
|
||||||
[key: string]: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface UseTagsOptions {
|
interface UseTagsOptions {
|
||||||
apiClient: ApiClient;
|
apiClient: ApiClient;
|
||||||
notifyApiError: (error: unknown, fallback: string) => void;
|
notifyApiError: (error: unknown, fallback: string) => void;
|
||||||
@@ -38,7 +32,7 @@ const useTags = ({
|
|||||||
setActiveTagFilters,
|
setActiveTagFilters,
|
||||||
mapDocumentCaches,
|
mapDocumentCaches,
|
||||||
}: UseTagsOptions) => {
|
}: UseTagsOptions) => {
|
||||||
const [tags, setTags] = useState<TagEntry[]>([]);
|
const [tags, setTags] = useState<Tag[]>([]);
|
||||||
|
|
||||||
const refreshTags = useCallback(async () => {
|
const refreshTags = useCallback(async () => {
|
||||||
const requestTenantId = tenantIdRef.current;
|
const requestTenantId = tenantIdRef.current;
|
||||||
|
|||||||
@@ -14,6 +14,29 @@ export interface DocumentCorrespondent {
|
|||||||
count?: number;
|
count?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tag entity as returned by the API (includes usage_count).
|
||||||
|
* Use DocumentTag for the embedded version on documents.
|
||||||
|
*/
|
||||||
|
export interface Tag {
|
||||||
|
id?: Identifier;
|
||||||
|
label?: string;
|
||||||
|
color?: string | null;
|
||||||
|
usage_count?: number;
|
||||||
|
[key: string]: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A correspondent entity as returned by the API.
|
||||||
|
* Use DocumentCorrespondent for the embedded version on documents.
|
||||||
|
*/
|
||||||
|
export interface Correspondent {
|
||||||
|
id?: Identifier;
|
||||||
|
name?: string;
|
||||||
|
usage_count?: number;
|
||||||
|
[key: string]: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
export interface DocumentVersion {
|
export interface DocumentVersion {
|
||||||
assets?: Record<string, Asset> | Asset[] | null;
|
assets?: Record<string, Asset> | Asset[] | null;
|
||||||
metadata?: Record<string, unknown> & { page_count?: number } | null;
|
metadata?: Record<string, unknown> & { page_count?: number } | null;
|
||||||
|
|||||||
Reference in New Issue
Block a user