diff --git a/webos/src/pillars/pipeline/PipelinePillar.tsx b/webos/src/pillars/pipeline/PipelinePillar.tsx
index b5acf26..07958db 100644
--- a/webos/src/pillars/pipeline/PipelinePillar.tsx
+++ b/webos/src/pillars/pipeline/PipelinePillar.tsx
@@ -1,4 +1,4 @@
-import { useState } from 'react';
+import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { motion } from 'framer-motion';
import { QDRing } from './client360/QDRing';
@@ -7,7 +7,11 @@ import styles from './PipelinePillar.module.css';
export default function PipelinePillar() {
const [viewMode, setViewMode] = useState<'board' | 'list'>('board');
- const { stages, isLoading } = useKanban();
+ const { stages, isLoading, isError, refetch } = useKanban();
+
+ useEffect(() => {
+ void refetch();
+ }, [refetch]);
return (
@@ -36,6 +40,8 @@ export default function PipelinePillar() {
{isLoading ? (
+ ) : isError ? (
+
void refetch()} />
) : viewMode === 'board' ? (
) : (
@@ -45,6 +51,16 @@ export default function PipelinePillar() {
);
}
+function PipelineError({ onRetry }: { onRetry: () => void }) {
+ return (
+
+ Pipeline data could not be loaded.
+ Retry the CRM read model without refreshing the whole app.
+
+
+ );
+}
+
interface Stage {
id: string;
label: string;
diff --git a/webos/src/pillars/pipeline/client360/Client360.tsx b/webos/src/pillars/pipeline/client360/Client360.tsx
index 530e471..766f548 100644
--- a/webos/src/pillars/pipeline/client360/Client360.tsx
+++ b/webos/src/pillars/pipeline/client360/Client360.tsx
@@ -1,5 +1,6 @@
import { useState, useEffect } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
+import { useQueryClient } from '@tanstack/react-query';
import { motion, AnimatePresence } from 'framer-motion';
import { QDRing } from './QDRing';
import { ConversationsTab } from './tabs/Conversations';
@@ -30,12 +31,17 @@ const TABS: { id: Tab; label: string }[] = [
export default function Client360() {
const { personId } = useParams<{ personId: string }>();
const navigate = useNavigate();
+ const queryClient = useQueryClient();
const [activeTab, setActiveTab] = useState('conversations');
const { client, isLoading, error } = useClient360(personId!);
+ const backToPipeline = () => {
+ void queryClient.invalidateQueries({ queryKey: ['kanban'] });
+ navigate('/pipeline', { replace: true });
+ };
if (isLoading) return ;
- if (error || !client) return navigate('/pipeline')} />;
+ if (error || !client) return ;
const qdColor =
client.qdScore >= 70 ? 'var(--color-green)' :
@@ -52,7 +58,7 @@ export default function Client360() {
{/* Back button */}