feat: analytics dashboards & two-tier feedback system (#78)
* docs: add analytics & user feedback design document Covers team analytics, personal analytics, flow analytics, step-level thumbs up/down feedback, and flow CSAT ratings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add analytics & feedback implementation plan 12-task TDD plan covering session ratings, step feedback, team/personal/flow analytics endpoints, and frontend pages. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add session_ratings table and analytics indexes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add SessionRating model and analytics schemas Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add session CSAT rating endpoint with tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add step thumbs feedback and /ratings alias routes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add team, personal, and flow analytics endpoints Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add recharts, analytics types, and API client Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add inline step thumbs up/down feedback during sessions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add CSAT rating modal after session completion Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add Team Analytics page with charts and leaderboards Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add Flow Analytics panel with step dropoff and CSAT data Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add My Analytics page with personal stats and charts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit was merged in pull request #78.
This commit is contained in:
@@ -14,6 +14,8 @@ import { Plus, CheckCircle, ArrowRight, Clock, Terminal, Clipboard, Check, Copy,
|
||||
import { toast } from '@/lib/toast'
|
||||
import { Modal } from '@/components/common/Modal'
|
||||
import { ShareSessionModal } from '@/components/session/ShareSessionModal'
|
||||
import { CSATModal, hasBeenRated } from '@/components/session/CSATModal'
|
||||
import { StepFeedback } from '@/components/session/StepFeedback'
|
||||
import { buildSessionShareUrl, getLatestActiveShareForSession } from '@/lib/sessionShare'
|
||||
|
||||
interface LocationState {
|
||||
@@ -52,6 +54,7 @@ export function TreeNavigationPage() {
|
||||
const [isCopyingForTicket, setIsCopyingForTicket] = useState(false)
|
||||
const [showSharePopover, setShowSharePopover] = useState(false)
|
||||
const [showShareModal, setShowShareModal] = useState(false)
|
||||
const [showCsatModal, setShowCsatModal] = useState(false)
|
||||
const [copiedShareLink, setCopiedShareLink] = useState(false)
|
||||
const [isCopyingShareLink, setIsCopyingShareLink] = useState(false)
|
||||
const sharePopoverRef = useRef<HTMLDivElement>(null)
|
||||
@@ -195,6 +198,13 @@ export function TreeNavigationPage() {
|
||||
setCompletionSource('standard')
|
||||
}
|
||||
|
||||
const handleCsatClose = () => {
|
||||
setShowCsatModal(false)
|
||||
if (session) {
|
||||
navigate(`/sessions/${session.id}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Custom step flow (creation, post-step actions, continuation, branching, forking)
|
||||
const customStepFlow = useCustomStepFlow({
|
||||
tree,
|
||||
@@ -450,6 +460,8 @@ export function TreeNavigationPage() {
|
||||
setPendingCompletionDecision(null)
|
||||
if (completionSource === 'custom' && customStepFlow.customSteps.length > 0) {
|
||||
customStepFlow.setShowForkModal(true)
|
||||
} else if (!hasBeenRated(session.id)) {
|
||||
setShowCsatModal(true)
|
||||
} else {
|
||||
navigate(`/sessions/${session.id}`)
|
||||
}
|
||||
@@ -1089,6 +1101,13 @@ export function TreeNavigationPage() {
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Step Feedback */}
|
||||
{session && (currentNode || currentCustomStep) && (
|
||||
<div className="mt-3 flex justify-end border-t border-border pt-3">
|
||||
<StepFeedback stepId={currentCustomStep?.id || currentNodeId} sessionId={session.id} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Notes */}
|
||||
<div className="mt-6 border-t border-border pt-4">
|
||||
<label className="block text-sm font-medium text-foreground">
|
||||
@@ -1180,6 +1199,14 @@ export function TreeNavigationPage() {
|
||||
isSubmitting={isCompleting}
|
||||
/>
|
||||
|
||||
{session && (
|
||||
<CSATModal
|
||||
isOpen={showCsatModal}
|
||||
onClose={handleCsatClose}
|
||||
sessionId={session.id}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Keyboard Shortcuts Modal */}
|
||||
<Modal
|
||||
isOpen={shortcutsModalOpen}
|
||||
|
||||
Reference in New Issue
Block a user