feat: add CSV import, activity timeline, and AI insights widget
- CSV Import: modal with file picker, auto column mapping, preview table, import progress - Activity Timeline: new tab on client detail showing all communications, events, status changes - AI Insights Widget: dashboard card showing stale clients, upcoming birthdays, suggested follow-ups - Import button on Clients page header
This commit is contained in:
@@ -1,18 +1,20 @@
|
||||
import { useEffect, useState, useMemo } from 'react';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { useClientsStore } from '@/stores/clients';
|
||||
import { Search, Plus, Users, X } from 'lucide-react';
|
||||
import { Search, Plus, Users, X, Upload } from 'lucide-react';
|
||||
import { cn, getRelativeTime, getInitials } from '@/lib/utils';
|
||||
import Badge from '@/components/Badge';
|
||||
import EmptyState from '@/components/EmptyState';
|
||||
import { PageLoader } from '@/components/LoadingSpinner';
|
||||
import Modal from '@/components/Modal';
|
||||
import ClientForm from '@/components/ClientForm';
|
||||
import CSVImportModal from '@/components/CSVImportModal';
|
||||
|
||||
export default function ClientsPage() {
|
||||
const location = useLocation();
|
||||
const { clients, isLoading, searchQuery, selectedTag, setSearchQuery, setSelectedTag, fetchClients, createClient } = useClientsStore();
|
||||
const [showCreate, setShowCreate] = useState(false);
|
||||
const [showImport, setShowImport] = useState(false);
|
||||
const [creating, setCreating] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -72,13 +74,22 @@ export default function ClientsPage() {
|
||||
<h1 className="text-2xl font-bold text-slate-900">Clients</h1>
|
||||
<p className="text-slate-500 text-sm mt-1">{clients.length} contacts in your network</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setShowCreate(true)}
|
||||
className="flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg text-sm font-medium hover:bg-blue-700 transition-colors"
|
||||
>
|
||||
<Plus className="w-4 h-4" />
|
||||
Add Client
|
||||
</button>
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
onClick={() => setShowImport(true)}
|
||||
className="flex items-center gap-2 px-4 py-2 bg-white border border-slate-200 text-slate-700 rounded-lg text-sm font-medium hover:bg-slate-50 transition-colors"
|
||||
>
|
||||
<Upload className="w-4 h-4" />
|
||||
Import CSV
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setShowCreate(true)}
|
||||
className="flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg text-sm font-medium hover:bg-blue-700 transition-colors"
|
||||
>
|
||||
<Plus className="w-4 h-4" />
|
||||
Add Client
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Search + Tags */}
|
||||
@@ -175,6 +186,13 @@ export default function ClientsPage() {
|
||||
<Modal isOpen={showCreate} onClose={() => setShowCreate(false)} title="Add Client" size="lg">
|
||||
<ClientForm onSubmit={handleCreate} loading={creating} />
|
||||
</Modal>
|
||||
|
||||
{/* Import CSV Modal */}
|
||||
<CSVImportModal
|
||||
isOpen={showImport}
|
||||
onClose={() => setShowImport(false)}
|
||||
onComplete={() => fetchClients()}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user