feat: agent detail page, campaign edit slideout, integration config, auth persistence

Agent Detail (/agent/:id):
- Individual agent performance page with KPI cards + call log table
- Clickable agent names in dashboard table link to detail view
- Back button to Team Dashboard

Campaign Edit Slideout:
- Edit button on each campaign card
- Slideout with name, status, budget, dates
- Saves via updateCampaign GraphQL mutation

Integration Config Slideout:
- Configure button on each integration card
- Per-integration form fields (Ozonetel, WhatsApp, Facebook, etc.)
- Copy webhook URL, OAuth placeholder buttons

Auth Persistence:
- User data persisted to localStorage on login
- Session restored on page refresh — no more logout on F5
- Stale tokens cleaned up automatically

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-19 16:32:58 +05:30
parent bb004744f4
commit 567f9f2d72
8 changed files with 833 additions and 24 deletions

View File

@@ -1,4 +1,5 @@
import { useMemo } from 'react';
import { Link } from 'react-router';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faUserHeadset } from '@fortawesome/pro-duotone-svg-icons';
import { Avatar } from '@/components/base/avatar/avatar';
@@ -81,10 +82,12 @@ export const AgentTable = ({ calls }: AgentTableProps) => {
{(agent) => (
<Table.Row id={agent.id}>
<Table.Cell>
<div className="flex items-center gap-2">
<Avatar size="xs" initials={agent.initials} />
<span className="text-sm font-medium text-primary">{agent.name}</span>
</div>
<Link to={`/agent/${encodeURIComponent(agent.name)}`} className="no-underline">
<div className="flex items-center gap-2">
<Avatar size="xs" initials={agent.initials} />
<span className="text-sm font-medium text-brand-secondary hover:text-brand-secondary_hover transition duration-100 ease-linear">{agent.name}</span>
</div>
</Link>
</Table.Cell>
<Table.Cell><span className="text-sm text-success-primary">{agent.inbound}</span></Table.Cell>
<Table.Cell><span className="text-sm text-brand-secondary">{agent.outbound}</span></Table.Cell>