mirror of
https://github.com/harivansh-afk/Austens-Wedding-Guide.git
synced 2026-04-15 08:03:41 +00:00
debugging 2
This commit is contained in:
parent
72193f9967
commit
4870fb5e92
2 changed files with 50 additions and 48 deletions
|
|
@ -106,7 +106,7 @@ ${colorConfig
|
||||||
const ChartTooltip = RechartsPrimitive.Tooltip;
|
const ChartTooltip = RechartsPrimitive.Tooltip;
|
||||||
|
|
||||||
interface PayloadItem {
|
interface PayloadItem {
|
||||||
dataKey?: string;
|
dataKey?: string | number;
|
||||||
name?: string;
|
name?: string;
|
||||||
value?: number;
|
value?: number;
|
||||||
payload?: {
|
payload?: {
|
||||||
|
|
@ -125,7 +125,8 @@ interface CustomTooltipProps extends Omit<TooltipProps<ValueType, NameType>, 'fo
|
||||||
labelKey?: string;
|
labelKey?: string;
|
||||||
labelClassName?: string;
|
labelClassName?: string;
|
||||||
color?: string;
|
color?: string;
|
||||||
formatter?: (value: ValueType, name: string, props: PayloadItem, index: number, payload: PayloadItem) => React.ReactNode;
|
formatter?: (value: ValueType, name: string, props: PayloadItem, index: number, payload: PayloadItem[]) => React.ReactNode;
|
||||||
|
payload?: PayloadItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const getPayloadConfigFromPayload = (config: ChartConfig, payload: PayloadItem, key: string) => {
|
const getPayloadConfigFromPayload = (config: ChartConfig, payload: PayloadItem, key: string) => {
|
||||||
|
|
@ -205,7 +206,7 @@ const ChartTooltipContent = React.forwardRef<HTMLDivElement, CustomTooltipProps>
|
||||||
>
|
>
|
||||||
{!nestLabel ? tooltipLabel : null}
|
{!nestLabel ? tooltipLabel : null}
|
||||||
<div className="grid gap-1.5">
|
<div className="grid gap-1.5">
|
||||||
{payload.map((item: PayloadItem, index: number) => {
|
{payload.map((item, index) => {
|
||||||
const key = `${nameKey || item.name || item.dataKey || 'value'}`;
|
const key = `${nameKey || item.name || item.dataKey || 'value'}`;
|
||||||
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
||||||
const indicatorColor = color || (item.payload?.fill || item.color);
|
const indicatorColor = color || (item.payload?.fill || item.color);
|
||||||
|
|
@ -219,7 +220,7 @@ const ChartTooltipContent = React.forwardRef<HTMLDivElement, CustomTooltipProps>
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{formatter && item?.value !== undefined && item.name ? (
|
{formatter && item?.value !== undefined && item.name ? (
|
||||||
formatter(item.value, item.name, item, index, item)
|
formatter(item.value, item.name, item, index, payload)
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{itemConfig?.icon ? (
|
{itemConfig?.icon ? (
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,12 @@ import { useRef, useEffect, useState, useCallback } from 'react';
|
||||||
import { characterNetwork } from '../data/character-network';
|
import { characterNetwork } from '../data/character-network';
|
||||||
import { CharacterNode, Relationship, BookNode } from '../types/character-network';
|
import { CharacterNode, Relationship, BookNode } from '../types/character-network';
|
||||||
import { Box, Typography, Paper, Grid, IconButton, Tooltip, Chip, Divider, Container, CircularProgress, Fade } from '@mui/material';
|
import { Box, Typography, Paper, Grid, IconButton, Tooltip, Chip, Divider, Container, CircularProgress, Fade } from '@mui/material';
|
||||||
import { ForceGraph2D, ForceGraphMethods } from 'react-force-graph';
|
import { ForceGraph2D as ForceGraph } from 'react-force-graph';
|
||||||
import { ArrowBack, Help, ZoomIn, ZoomOut, CenterFocusStrong } from '@mui/icons-material';
|
import { ArrowBack, Help, ZoomIn, ZoomOut, CenterFocusStrong } from '@mui/icons-material';
|
||||||
import * as d3 from 'd3';
|
import * as d3 from 'd3';
|
||||||
|
|
||||||
interface NetworkNode extends d3.SimulationNodeDatum {
|
// Base node interface extending SimulationNodeDatum
|
||||||
|
interface BaseNetworkNode extends d3.SimulationNodeDatum {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
type: 'protagonist' | 'antagonist' | 'supporting' | 'book' | 'character';
|
type: 'protagonist' | 'antagonist' | 'supporting' | 'book' | 'character';
|
||||||
|
|
@ -21,23 +22,37 @@ interface NetworkNode extends d3.SimulationNodeDatum {
|
||||||
fy?: number;
|
fy?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NetworkLink {
|
// Book-specific node interface
|
||||||
source: string;
|
interface NetworkBookNode extends BaseNetworkNode {
|
||||||
target: string;
|
type: 'book';
|
||||||
|
year: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Character-specific node interface
|
||||||
|
interface NetworkCharacterNode extends BaseNetworkNode {
|
||||||
|
type: 'protagonist' | 'antagonist' | 'supporting' | 'character';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Union type for all possible node types
|
||||||
|
type NetworkNode = NetworkBookNode | NetworkCharacterNode;
|
||||||
|
|
||||||
|
interface NetworkLink extends d3.SimulationLinkDatum<NetworkNode> {
|
||||||
|
source: string | NetworkNode;
|
||||||
|
target: string | NetworkNode;
|
||||||
type: string;
|
type: string;
|
||||||
color: string;
|
color: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Proper typing for ForceGraph methods
|
// Proper typing for ForceGraph methods
|
||||||
interface ForceGraphMethods {
|
interface ForceGraphMethods<NodeType extends d3.SimulationNodeDatum = NetworkNode, LinkType extends d3.SimulationLinkDatum<NodeType> = NetworkLink> {
|
||||||
zoom: (k?: number) => number;
|
zoom: (k?: number) => number;
|
||||||
zoomToFit: (duration?: number, padding?: number) => void;
|
zoomToFit: (duration?: number, padding?: number) => void;
|
||||||
d3Force: (forceName: string, force?: d3.Force<d3.SimulationNodeDatum, undefined>) => void;
|
d3Force: (forceName: string, force?: d3.Force<NodeType, LinkType>) => void;
|
||||||
d3ReheatSimulation: () => void;
|
d3ReheatSimulation: () => void;
|
||||||
getZoom: () => number;
|
getZoom: () => number;
|
||||||
}
|
}
|
||||||
|
|
||||||
type ForceGraphInstance = ForceGraphMethods;
|
type ForceGraphInstance = ForceGraphMethods<NetworkNode, NetworkLink>;
|
||||||
|
|
||||||
// Add sage theme colors after the interface definitions
|
// Add sage theme colors after the interface definitions
|
||||||
const sageColors = {
|
const sageColors = {
|
||||||
|
|
@ -75,11 +90,11 @@ const getPentagonPoint = (index: number, total: number, radius: number, centerX:
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function NetworkVisualization() {
|
export default function NetworkVisualization() {
|
||||||
const [selectedNode, setSelectedNode] = useState<CharacterNode | BookNode | null>(null);
|
const [selectedNode, setSelectedNode] = useState<NetworkNode | null>(null);
|
||||||
const [selectedRelationships, setSelectedRelationships] = useState<Relationship[]>([]);
|
const [selectedRelationships, setSelectedRelationships] = useState<Relationship[]>([]);
|
||||||
const [selectedBook, setSelectedBook] = useState<string | null>(null);
|
const [selectedBook, setSelectedBook] = useState<string | null>(null);
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const fgRef = useRef<ForceGraphMethods>(null);
|
const fgRef = useRef<ForceGraphMethods<NetworkNode, NetworkLink>>();
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [isGraphReady, setIsGraphReady] = useState(false);
|
const [isGraphReady, setIsGraphReady] = useState(false);
|
||||||
const [dimensions, setDimensions] = useState({ width: 800, height: 700 });
|
const [dimensions, setDimensions] = useState({ width: 800, height: 700 });
|
||||||
|
|
@ -118,41 +133,27 @@ export default function NetworkVisualization() {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Update the node interaction handlers
|
// Update the node interaction handlers
|
||||||
const handleNodeClick = (node: NetworkNode) => {
|
const handleNodeClick = useCallback((node: NetworkNode) => {
|
||||||
// Book node click
|
|
||||||
if (node.type === 'book') {
|
if (node.type === 'book') {
|
||||||
const bookNode = characterNetwork.books.find(b => b.id === node.id);
|
const bookNode: NetworkBookNode = {
|
||||||
if (bookNode) {
|
...node,
|
||||||
// Update all states synchronously
|
year: (node as NetworkBookNode).year
|
||||||
setSelectedBook(node.id);
|
};
|
||||||
setSelectedNode(bookNode);
|
setSelectedBook(node.id);
|
||||||
setSelectedRelationships([]);
|
setSelectedNode(bookNode);
|
||||||
|
setSelectedRelationships([]);
|
||||||
// Trigger force simulation update after state changes
|
} else {
|
||||||
requestAnimationFrame(() => {
|
const characterNode: NetworkCharacterNode = {
|
||||||
if (fgRef.current) {
|
...node,
|
||||||
fgRef.current.d3ReheatSimulation();
|
type: node.type as 'protagonist' | 'antagonist' | 'supporting' | 'character'
|
||||||
}
|
};
|
||||||
});
|
const relations = characterNetwork.relationships.filter(
|
||||||
}
|
(rel) => rel.source === node.id || rel.target === node.id
|
||||||
return;
|
);
|
||||||
|
setSelectedNode(characterNode);
|
||||||
|
setSelectedRelationships(relations);
|
||||||
}
|
}
|
||||||
|
}, []);
|
||||||
// Character node click - only process if we're in a book view
|
|
||||||
if (selectedBook) {
|
|
||||||
const characterNode = characterNetwork.nodes.find(n => n.id === node.id);
|
|
||||||
if (characterNode) {
|
|
||||||
// Get relationships first
|
|
||||||
const relations = characterNetwork.relationships.filter(
|
|
||||||
r => r.source === node.id || r.target === node.id
|
|
||||||
);
|
|
||||||
|
|
||||||
// Update states synchronously
|
|
||||||
setSelectedNode(characterNode);
|
|
||||||
setSelectedRelationships(relations);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleBackClick = () => {
|
const handleBackClick = () => {
|
||||||
setSelectedBook(null);
|
setSelectedBook(null);
|
||||||
|
|
@ -533,7 +534,7 @@ export default function NetworkVisualization() {
|
||||||
{/* Graph container */}
|
{/* Graph container */}
|
||||||
<Fade in={!isLoading && isGraphReady} timeout={500}>
|
<Fade in={!isLoading && isGraphReady} timeout={500}>
|
||||||
<Box sx={{ width: '100%', height: '100%' }}>
|
<Box sx={{ width: '100%', height: '100%' }}>
|
||||||
<ForceGraph2D
|
<ForceGraph
|
||||||
ref={fgRef}
|
ref={fgRef}
|
||||||
graphData={getGraphData()}
|
graphData={getGraphData()}
|
||||||
onNodeClick={handleNodeClick}
|
onNodeClick={handleNodeClick}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue