shadow-over-bishkek001/dialogEditor/src/components/RightPanel/RightPanel.tsx
2026-06-05 21:17:51 +03:00

103 lines
3.6 KiB
TypeScript

import { useDialogueStore } from '../../store/dialogueStore';
import { LineInspector } from './inspectors/LineInspector';
import { ChoiceInspector } from './inspectors/ChoiceInspector';
import { ConditionInspector } from './inspectors/ConditionInspector';
import { SetFlagInspector } from './inspectors/SetFlagInspector';
import { CutsceneStartInspector, EndInspector } from './inspectors/OtherInspectors';
import { DialogueNode } from '../../types/dialogue';
import styles from './RightPanel.module.css';
// Helper to update start node ID
function useUpdateStart() {
const store = useDialogueStore;
return (dialogueId: string, start: string) => {
store.setState(state => {
const d = state.file?.dialogues.find(x => x.id === dialogueId);
if (d) d.start = start;
});
};
}
export function RightPanel() {
const { file, selectedDialogueId, selectedNodeId } = useDialogueStore();
const updateStart = useUpdateStart();
const dialogue = file?.dialogues.find(d => d.id === selectedDialogueId);
if (!dialogue) {
return (
<div className={styles.panel}>
<div className={styles.emptyMsg}>No dialogue selected</div>
</div>
);
}
if (!selectedNodeId) {
return (
<div className={styles.panel}>
<div className={styles.dialogueMeta}>
<div className={styles.metaHeader}>Dialogue Properties</div>
<div>
<label className={styles.label}>ID</label>
<input className={styles.input} value={dialogue.id} readOnly />
</div>
<div style={{ marginTop: 8 }}>
<label className={styles.label}>Start node</label>
<input
className={styles.input}
value={dialogue.start}
onChange={e => {
if (selectedDialogueId) updateStart(selectedDialogueId, e.target.value);
}}
list="startNodeList"
/>
<datalist id="startNodeList">
{dialogue.nodes.map(n => <option key={n.id} value={n.id} />)}
</datalist>
</div>
<div className={styles.emptyHint} style={{ marginTop: 16 }}>
Click a node in the graph to inspect it.
</div>
<div style={{ marginTop: 12 }}>
<div className={styles.metaHeader}>Node Count</div>
<div className={styles.statRow}>
{(['Line', 'Choice', 'Condition', 'SetFlag', 'CutsceneStart', 'End'] as DialogueNode['type'][]).map(t => {
const count = dialogue.nodes.filter(n => n.type === t).length;
return count > 0 ? (
<span key={t} className={styles.statPill}>{t}: {count}</span>
) : null;
})}
</div>
</div>
</div>
</div>
);
}
const node = dialogue.nodes.find(n => n.id === selectedNodeId);
if (!node) return null;
return (
<div className={styles.panel}>
{node.type === 'Line' && (
<LineInspector node={node} dialogueId={dialogue.id} />
)}
{node.type === 'Choice' && (
<ChoiceInspector node={node} dialogueId={dialogue.id} />
)}
{node.type === 'Condition' && (
<ConditionInspector node={node} dialogueId={dialogue.id} />
)}
{node.type === 'SetFlag' && (
<SetFlagInspector node={node} dialogueId={dialogue.id} />
)}
{node.type === 'CutsceneStart' && (
<CutsceneStartInspector node={node} dialogueId={dialogue.id} />
)}
{node.type === 'End' && (
<EndInspector node={node} dialogueId={dialogue.id} />
)}
</div>
);
}