feat(registratura): rework with company-prefixed numbering, directions, deadlines, attachments
- Company-specific numbering (B-0001/2026, US-0001/2026, SDT-0001/2026) - Direction: Intrat/Ieșit replaces old 3-way type - 9 document types: Contract, Ofertă, Factură, Scrisoare, etc. - Status simplified to Deschis/Închis with cascade close for linked entries - Address Book autocomplete for sender/recipient - Deadline tracking with overdue day counter - File attachment support (base64 encoding) - Linked entries system Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,13 +3,14 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { useStorage } from '@/core/storage';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import type { RegistryEntry, RegistryEntryType, RegistryEntryStatus } from '../types';
|
||||
import type { RegistryEntry, RegistryDirection, RegistryStatus, DocumentType } from '../types';
|
||||
import { getAllEntries, saveEntry, deleteEntry, generateRegistryNumber } from '../services/registry-service';
|
||||
|
||||
export interface RegistryFilters {
|
||||
search: string;
|
||||
type: RegistryEntryType | 'all';
|
||||
status: RegistryEntryStatus | 'all';
|
||||
direction: RegistryDirection | 'all';
|
||||
status: RegistryStatus | 'all';
|
||||
documentType: DocumentType | 'all';
|
||||
company: string;
|
||||
}
|
||||
|
||||
@@ -19,8 +20,9 @@ export function useRegistry() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [filters, setFilters] = useState<RegistryFilters>({
|
||||
search: '',
|
||||
type: 'all',
|
||||
direction: 'all',
|
||||
status: 'all',
|
||||
documentType: 'all',
|
||||
company: 'all',
|
||||
});
|
||||
|
||||
@@ -36,18 +38,18 @@ export function useRegistry() {
|
||||
|
||||
const addEntry = useCallback(async (data: Omit<RegistryEntry, 'id' | 'number' | 'createdAt' | 'updatedAt'>) => {
|
||||
const now = new Date().toISOString();
|
||||
const nextIndex = entries.length + 1;
|
||||
const number = generateRegistryNumber(data.company, data.date, entries);
|
||||
const entry: RegistryEntry = {
|
||||
...data,
|
||||
id: uuid(),
|
||||
number: generateRegistryNumber(data.date, nextIndex),
|
||||
number,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
await saveEntry(storage, entry);
|
||||
await refresh();
|
||||
return entry;
|
||||
}, [storage, refresh, entries.length]);
|
||||
}, [storage, refresh, entries]);
|
||||
|
||||
const updateEntry = useCallback(async (id: string, updates: Partial<RegistryEntry>) => {
|
||||
const existing = entries.find((e) => e.id === id);
|
||||
@@ -69,13 +71,35 @@ export function useRegistry() {
|
||||
await refresh();
|
||||
}, [storage, refresh]);
|
||||
|
||||
/** Close an entry and optionally its linked entries */
|
||||
const closeEntry = useCallback(async (id: string, closeLinked: boolean) => {
|
||||
const entry = entries.find((e) => e.id === id);
|
||||
if (!entry) return;
|
||||
await updateEntry(id, { status: 'inchis' });
|
||||
if (closeLinked && entry.linkedEntryIds.length > 0) {
|
||||
for (const linkedId of entry.linkedEntryIds) {
|
||||
const linked = entries.find((e) => e.id === linkedId);
|
||||
if (linked && linked.status !== 'inchis') {
|
||||
const updatedLinked: RegistryEntry = {
|
||||
...linked,
|
||||
status: 'inchis',
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
await saveEntry(storage, updatedLinked);
|
||||
}
|
||||
}
|
||||
await refresh();
|
||||
}
|
||||
}, [entries, updateEntry, storage, refresh]);
|
||||
|
||||
const updateFilter = useCallback(<K extends keyof RegistryFilters>(key: K, value: RegistryFilters[K]) => {
|
||||
setFilters((prev) => ({ ...prev, [key]: value }));
|
||||
}, []);
|
||||
|
||||
const filteredEntries = entries.filter((entry) => {
|
||||
if (filters.type !== 'all' && entry.type !== filters.type) return false;
|
||||
if (filters.direction !== 'all' && entry.direction !== filters.direction) return false;
|
||||
if (filters.status !== 'all' && entry.status !== filters.status) return false;
|
||||
if (filters.documentType !== 'all' && entry.documentType !== filters.documentType) return false;
|
||||
if (filters.company !== 'all' && entry.company !== filters.company) return false;
|
||||
if (filters.search) {
|
||||
const q = filters.search.toLowerCase();
|
||||
@@ -83,7 +107,7 @@ export function useRegistry() {
|
||||
entry.subject.toLowerCase().includes(q) ||
|
||||
entry.sender.toLowerCase().includes(q) ||
|
||||
entry.recipient.toLowerCase().includes(q) ||
|
||||
entry.number.includes(q)
|
||||
entry.number.toLowerCase().includes(q)
|
||||
);
|
||||
}
|
||||
return true;
|
||||
@@ -98,6 +122,7 @@ export function useRegistry() {
|
||||
addEntry,
|
||||
updateEntry,
|
||||
removeEntry,
|
||||
closeEntry,
|
||||
refresh,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user