mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-11 18:28:15 +00:00
feat: add exit animations on lead cards and cross-page filter continuity
- Wrap lead cards in AnimatePresence/motion.div so they fade+slide out when removed from the NEW filter - Update "View All" link to pass active source filter as ?source= URL param - Initialize AllLeadsPage sourceFilter from URL search params on mount Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
|
import { useSearchParams } from 'react-router';
|
||||||
import { ArrowLeft, Download01, FilterLines, SearchLg, SwitchVertical01 } from '@untitledui/icons';
|
import { ArrowLeft, Download01, FilterLines, SearchLg, SwitchVertical01 } from '@untitledui/icons';
|
||||||
import { Button } from '@/components/base/buttons/button';
|
import { Button } from '@/components/base/buttons/button';
|
||||||
import { Input } from '@/components/base/input/input';
|
import { Input } from '@/components/base/input/input';
|
||||||
@@ -29,11 +30,13 @@ const PAGE_SIZE = 25;
|
|||||||
|
|
||||||
export const AllLeadsPage = () => {
|
export const AllLeadsPage = () => {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
|
const [searchParams] = useSearchParams();
|
||||||
|
const initialSource = searchParams.get('source') as LeadSource | null;
|
||||||
const [tab, setTab] = useState<TabKey>('new');
|
const [tab, setTab] = useState<TabKey>('new');
|
||||||
const [selectedIds, setSelectedIds] = useState<string[]>([]);
|
const [selectedIds, setSelectedIds] = useState<string[]>([]);
|
||||||
const [sortField, setSortField] = useState('createdAt');
|
const [sortField, setSortField] = useState('createdAt');
|
||||||
const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('desc');
|
const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('desc');
|
||||||
const [sourceFilter, setSourceFilter] = useState<LeadSource | null>(null);
|
const [sourceFilter, setSourceFilter] = useState<LeadSource | null>(initialSource);
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
const [searchQuery, setSearchQuery] = useState('');
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { AnimatePresence, motion } from 'motion/react';
|
||||||
|
|
||||||
import { Button } from '@/components/base/buttons/button';
|
import { Button } from '@/components/base/buttons/button';
|
||||||
import { TopBar } from '@/components/layout/top-bar';
|
import { TopBar } from '@/components/layout/top-bar';
|
||||||
@@ -81,14 +82,24 @@ export const LeadWorkspacePage = () => {
|
|||||||
<div>
|
<div>
|
||||||
<div className="mb-3.5 flex items-center justify-between">
|
<div className="mb-3.5 flex items-center justify-between">
|
||||||
<h2 className="font-display text-md font-bold text-primary">New Leads</h2>
|
<h2 className="font-display text-md font-bold text-primary">New Leads</h2>
|
||||||
<Button href="/leads" color="link-color" size="sm">
|
<Button
|
||||||
View All {total} Leads
|
href={sourceFilter ? `/leads?source=${sourceFilter}` : '/leads'}
|
||||||
|
color="link-color"
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
|
View All {total} Leads →
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
|
<AnimatePresence>
|
||||||
{displayLeads.map((lead) => (
|
{displayLeads.map((lead) => (
|
||||||
<LeadCard
|
<motion.div
|
||||||
key={lead.id}
|
key={lead.id}
|
||||||
|
initial={{ opacity: 1, x: 0 }}
|
||||||
|
exit={{ opacity: 0, x: -20, height: 0, marginBottom: 0 }}
|
||||||
|
transition={{ duration: 0.3 }}
|
||||||
|
>
|
||||||
|
<LeadCard
|
||||||
lead={lead}
|
lead={lead}
|
||||||
onAssign={handleAssign}
|
onAssign={handleAssign}
|
||||||
onMessage={handleMessage}
|
onMessage={handleMessage}
|
||||||
@@ -97,7 +108,9 @@ export const LeadWorkspacePage = () => {
|
|||||||
onLogCall={handleLogCall}
|
onLogCall={handleLogCall}
|
||||||
onUpdateStatus={handleUpdateStatus}
|
onUpdateStatus={handleUpdateStatus}
|
||||||
/>
|
/>
|
||||||
|
</motion.div>
|
||||||
))}
|
))}
|
||||||
|
</AnimatePresence>
|
||||||
{displayLeads.length === 0 && (
|
{displayLeads.length === 0 && (
|
||||||
<p className="py-8 text-center text-sm text-tertiary">
|
<p className="py-8 text-center text-sm text-tertiary">
|
||||||
No leads match the current filters.
|
No leads match the current filters.
|
||||||
|
|||||||
Reference in New Issue
Block a user