refacto react component
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { Settings, MessageSquare, Sword, Users, Code, FileText, Upload } from 'lucide-react';
|
import { Settings, MessageSquare, Sword, Users, Code, FileText, Upload } from 'lucide-react';
|
||||||
import type { NPCConfiguration, DialogueConfiguration } from './types/npc';
|
import type { NPCConfiguration, DialogueConfiguration } from './types/npc';
|
||||||
import { NPCBasicSettings } from './components/NPCBasicSettings';
|
import { NPCBasicSettings } from './components/NPCBasicSettings';
|
||||||
@@ -26,8 +26,7 @@ function App() {
|
|||||||
|
|
||||||
const [dialogueConfig, setDialogueConfig] = useState<DialogueConfiguration | null>(null);
|
const [dialogueConfig, setDialogueConfig] = useState<DialogueConfiguration | null>(null);
|
||||||
|
|
||||||
// Handle dialogue creation when interaction type changes to dialogue
|
useEffect(() => {
|
||||||
React.useEffect(() => {
|
|
||||||
if (npcConfig.interaction.type === 'dialogue' && !dialogueConfig) {
|
if (npcConfig.interaction.type === 'dialogue' && !dialogueConfig) {
|
||||||
const newDialogue: DialogueConfiguration = {
|
const newDialogue: DialogueConfiguration = {
|
||||||
speakers: {
|
speakers: {
|
||||||
@@ -49,7 +48,7 @@ function App() {
|
|||||||
};
|
};
|
||||||
setDialogueConfig(newDialogue);
|
setDialogueConfig(newDialogue);
|
||||||
}
|
}
|
||||||
}, [npcConfig.interaction.type, dialogueConfig]);
|
}, [npcConfig.interaction.type]);
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{ id: 'basic', name: 'Basic Settings', icon: Settings },
|
{ id: 'basic', name: 'Basic Settings', icon: Settings },
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Plus, Trash2 } from 'lucide-react';
|
import { Plus, Trash2 } from 'lucide-react';
|
||||||
import type { NPCConfiguration, MoLangConfigVariable } from '../types/npc';
|
import type { NPCConfiguration, MoLangConfigVariable } from '../types/npc';
|
||||||
|
|
||||||
@@ -7,7 +6,7 @@ interface ConfigVariablesEditorProps {
|
|||||||
onChange: (config: NPCConfiguration) => void;
|
onChange: (config: NPCConfiguration) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ConfigVariablesEditor: React.FC<ConfigVariablesEditorProps> = ({ config, onChange }) => {
|
export function ConfigVariablesEditor({ config, onChange }: ConfigVariablesEditorProps) {
|
||||||
const addVariable = () => {
|
const addVariable = () => {
|
||||||
const newVariable: MoLangConfigVariable = {
|
const newVariable: MoLangConfigVariable = {
|
||||||
variableName: '',
|
variableName: '',
|
||||||
@@ -166,4 +165,4 @@ export const ConfigVariablesEditor: React.FC<ConfigVariablesEditorProps> = ({ co
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Plus, Trash2, MessageCircle } from 'lucide-react';
|
import { Plus, Trash2, MessageCircle } from 'lucide-react';
|
||||||
import type { DialogueConfiguration, DialoguePage, DialogueSpeaker } from '../types/npc';
|
import type { DialogueConfiguration, DialoguePage, DialogueSpeaker } from '../types/npc';
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ interface DialogueEditorProps {
|
|||||||
onChange: (dialogue: DialogueConfiguration) => void;
|
onChange: (dialogue: DialogueConfiguration) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DialogueEditor: React.FC<DialogueEditorProps> = ({ dialogue, onChange }) => {
|
export function DialogueEditor({ dialogue, onChange }: DialogueEditorProps) {
|
||||||
const [selectedPageId, setSelectedPageId] = useState<string | null>(null);
|
const [selectedPageId, setSelectedPageId] = useState<string | null>(null);
|
||||||
const [speakerEditMode, setSpeakerEditMode] = useState(false);
|
const [speakerEditMode, setSpeakerEditMode] = useState(false);
|
||||||
|
|
||||||
@@ -268,9 +268,12 @@ export const DialogueEditor: React.FC<DialogueEditorProps> = ({ dialogue, onChan
|
|||||||
<div className="font-medium text-sm">{page.id}</div>
|
<div className="font-medium text-sm">{page.id}</div>
|
||||||
<div className="text-xs text-gray-500">Speaker: {page.speaker}</div>
|
<div className="text-xs text-gray-500">Speaker: {page.speaker}</div>
|
||||||
<div className="text-xs text-gray-600 truncate">
|
<div className="text-xs text-gray-600 truncate">
|
||||||
{Array.isArray(page.lines)
|
{page.lines.length > 0
|
||||||
? (typeof page.lines[0] === 'string' ? page.lines[0] : page.lines[0]?.text || 'Expression')
|
? (typeof page.lines[0] === 'string'
|
||||||
: (typeof page.lines === 'string' ? page.lines : page.lines?.text || 'Expression')}
|
? page.lines[0]
|
||||||
|
: (page.lines[0] as { text?: string }).text || 'Expression'
|
||||||
|
)
|
||||||
|
: 'No lines'}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
@@ -306,7 +309,7 @@ export const DialogueEditor: React.FC<DialogueEditorProps> = ({ dialogue, onChan
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
interface PageEditorProps {
|
interface PageEditorProps {
|
||||||
page: DialoguePage;
|
page: DialoguePage;
|
||||||
@@ -314,7 +317,7 @@ interface PageEditorProps {
|
|||||||
onChange: (page: DialoguePage) => void;
|
onChange: (page: DialoguePage) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PageEditor: React.FC<PageEditorProps> = ({ page, speakers, onChange }) => {
|
function PageEditor({ page, speakers, onChange }: PageEditorProps) {
|
||||||
const updatePage = (field: keyof DialoguePage, value: any) => {
|
const updatePage = (field: keyof DialoguePage, value: any) => {
|
||||||
onChange({ ...page, [field]: value });
|
onChange({ ...page, [field]: value });
|
||||||
};
|
};
|
||||||
@@ -411,4 +414,4 @@ const PageEditor: React.FC<PageEditorProps> = ({ page, speakers, onChange }) =>
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useRef } from 'react';
|
import { useRef, useState } from 'react';
|
||||||
import { Upload, Download, FileText, AlertTriangle } from 'lucide-react';
|
import { Upload, Download, FileText, AlertTriangle } from 'lucide-react';
|
||||||
import type { NPCConfiguration, DialogueConfiguration } from '../types/npc';
|
import type { NPCConfiguration, DialogueConfiguration } from '../types/npc';
|
||||||
|
|
||||||
@@ -9,16 +9,16 @@ interface ImportExportProps {
|
|||||||
onDialogueConfigLoad: (config: DialogueConfiguration) => void;
|
onDialogueConfigLoad: (config: DialogueConfiguration) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ImportExport: React.FC<ImportExportProps> = ({
|
export function ImportExport({
|
||||||
npcConfig,
|
npcConfig,
|
||||||
dialogueConfig,
|
dialogueConfig,
|
||||||
onNPCConfigLoad,
|
onNPCConfigLoad,
|
||||||
onDialogueConfigLoad
|
onDialogueConfigLoad
|
||||||
}) => {
|
}: ImportExportProps) {
|
||||||
const npcFileInputRef = useRef<HTMLInputElement>(null);
|
const npcFileInputRef = useRef<HTMLInputElement>(null);
|
||||||
const dialogueFileInputRef = useRef<HTMLInputElement>(null);
|
const dialogueFileInputRef = useRef<HTMLInputElement>(null);
|
||||||
const [importError, setImportError] = React.useState<string | null>(null);
|
const [importError, setImportError] = useState<string | null>(null);
|
||||||
const [importSuccess, setImportSuccess] = React.useState<string | null>(null);
|
const [importSuccess, setImportSuccess] = useState<string | null>(null);
|
||||||
|
|
||||||
const handleFileRead = (
|
const handleFileRead = (
|
||||||
file: File,
|
file: File,
|
||||||
@@ -313,4 +313,4 @@ export const ImportExport: React.FC<ImportExportProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import React from 'react';
|
import { useState } from 'react';
|
||||||
import { Download, Copy, Check } from 'lucide-react';
|
import { Download, Copy, Check } from 'lucide-react';
|
||||||
import type { NPCConfiguration, DialogueConfiguration } from '../types/npc';
|
import type { NPCConfiguration, DialogueConfiguration } from '../types/npc';
|
||||||
import { ValidationPanel } from './ValidationPanel';
|
import { ValidationPanel } from './ValidationPanel';
|
||||||
@@ -8,9 +8,9 @@ interface JSONPreviewProps {
|
|||||||
dialogueConfig: DialogueConfiguration | null;
|
dialogueConfig: DialogueConfiguration | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const JSONPreview: React.FC<JSONPreviewProps> = ({ npcConfig, dialogueConfig }) => {
|
export function JSONPreview({ npcConfig, dialogueConfig }: JSONPreviewProps) {
|
||||||
const [copiedNPC, setCopiedNPC] = React.useState(false);
|
const [copiedNPC, setCopiedNPC] = useState(false);
|
||||||
const [copiedDialogue, setCopiedDialogue] = React.useState(false);
|
const [copiedDialogue, setCopiedDialogue] = useState(false);
|
||||||
|
|
||||||
const cleanNPCConfig = (config: NPCConfiguration) => {
|
const cleanNPCConfig = (config: NPCConfiguration) => {
|
||||||
const cleaned = { ...config };
|
const cleaned = { ...config };
|
||||||
@@ -189,4 +189,4 @@ export const JSONPreview: React.FC<JSONPreviewProps> = ({ npcConfig, dialogueCon
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
import type { NPCConfiguration, NPCHitboxValue } from '../types/npc';
|
import type { NPCConfiguration, NPCHitboxValue } from '../types/npc';
|
||||||
|
|
||||||
interface NPCBasicSettingsProps {
|
interface NPCBasicSettingsProps {
|
||||||
@@ -6,7 +5,7 @@ interface NPCBasicSettingsProps {
|
|||||||
onChange: (config: NPCConfiguration) => void;
|
onChange: (config: NPCConfiguration) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const NPCBasicSettings: React.FC<NPCBasicSettingsProps> = ({ config, onChange }) => {
|
export function NPCBasicSettings({ config, onChange }: NPCBasicSettingsProps) {
|
||||||
const handleChange = (field: keyof NPCConfiguration, value: any) => {
|
const handleChange = (field: keyof NPCConfiguration, value: any) => {
|
||||||
onChange({ ...config, [field]: value });
|
onChange({ ...config, [field]: value });
|
||||||
};
|
};
|
||||||
@@ -196,4 +195,4 @@ export const NPCBasicSettings: React.FC<NPCBasicSettingsProps> = ({ config, onCh
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
import type { NPCConfiguration } from '../types/npc';
|
import type { NPCConfiguration } from '../types/npc';
|
||||||
|
|
||||||
interface NPCBattleConfigurationProps {
|
interface NPCBattleConfigurationProps {
|
||||||
@@ -6,7 +5,7 @@ interface NPCBattleConfigurationProps {
|
|||||||
onChange: (config: NPCConfiguration) => void;
|
onChange: (config: NPCConfiguration) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const NPCBattleConfiguration: React.FC<NPCBattleConfigurationProps> = ({ config, onChange }) => {
|
export function NPCBattleConfiguration({ config, onChange }: NPCBattleConfigurationProps) {
|
||||||
const handleChange = (field: keyof NPCConfiguration, value: any) => {
|
const handleChange = (field: keyof NPCConfiguration, value: any) => {
|
||||||
onChange({ ...config, [field]: value });
|
onChange({ ...config, [field]: value });
|
||||||
};
|
};
|
||||||
@@ -126,4 +125,4 @@ export const NPCBattleConfiguration: React.FC<NPCBattleConfigurationProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
import type { NPCConfiguration, NPCInteraction } from '../types/npc';
|
import type { NPCConfiguration, NPCInteraction } from '../types/npc';
|
||||||
|
|
||||||
interface NPCInteractionEditorProps {
|
interface NPCInteractionEditorProps {
|
||||||
@@ -6,7 +5,7 @@ interface NPCInteractionEditorProps {
|
|||||||
onChange: (config: NPCConfiguration) => void;
|
onChange: (config: NPCConfiguration) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const NPCInteractionEditor: React.FC<NPCInteractionEditorProps> = ({ config, onChange }) => {
|
export function NPCInteractionEditor({ config, onChange }: NPCInteractionEditorProps) {
|
||||||
const handleInteractionChange = (interaction: NPCInteraction) => {
|
const handleInteractionChange = (interaction: NPCInteraction) => {
|
||||||
onChange({ ...config, interaction });
|
onChange({ ...config, interaction });
|
||||||
};
|
};
|
||||||
@@ -112,4 +111,4 @@ export const NPCInteractionEditor: React.FC<NPCInteractionEditorProps> = ({ conf
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Plus, Trash2 } from 'lucide-react';
|
import { Plus, Trash2 } from 'lucide-react';
|
||||||
import type { NPCConfiguration, NPCPartyProvider, SimplePartyProvider, PoolPartyProvider, PoolEntry } from '../types/npc';
|
import type { NPCConfiguration, NPCPartyProvider, SimplePartyProvider, PoolPartyProvider, PoolEntry } from '../types/npc';
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ interface NPCPartyBuilderProps {
|
|||||||
onChange: (config: NPCConfiguration) => void;
|
onChange: (config: NPCConfiguration) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const NPCPartyBuilder: React.FC<NPCPartyBuilderProps> = ({ config, onChange }) => {
|
export function NPCPartyBuilder({ config, onChange }: NPCPartyBuilderProps) {
|
||||||
const [partyType, setPartyType] = useState<'simple' | 'pool' | 'script'>(config.party?.type || 'simple');
|
const [partyType, setPartyType] = useState<'simple' | 'pool' | 'script'>(config.party?.type || 'simple');
|
||||||
|
|
||||||
const handlePartyChange = (party: NPCPartyProvider) => {
|
const handlePartyChange = (party: NPCPartyProvider) => {
|
||||||
@@ -323,4 +323,4 @@ export const NPCPartyBuilder: React.FC<NPCPartyBuilderProps> = ({ config, onChan
|
|||||||
{partyType === 'script' && renderScriptParty()}
|
{partyType === 'script' && renderScriptParty()}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
import { AlertTriangle, CheckCircle, XCircle, AlertCircle } from 'lucide-react';
|
import { AlertTriangle, CheckCircle, XCircle, AlertCircle } from 'lucide-react';
|
||||||
import type { NPCConfiguration, DialogueConfiguration } from '../types/npc';
|
import type { NPCConfiguration, DialogueConfiguration } from '../types/npc';
|
||||||
import { validateNPCConfiguration, validateDialogueConfiguration, getValidationSummary } from '../utils/validation';
|
import { validateNPCConfiguration, validateDialogueConfiguration, getValidationSummary } from '../utils/validation';
|
||||||
@@ -9,14 +8,15 @@ interface ValidationPanelProps {
|
|||||||
dialogueConfig: DialogueConfiguration | null;
|
dialogueConfig: DialogueConfiguration | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ValidationPanel: React.FC<ValidationPanelProps> = ({ npcConfig, dialogueConfig }) => {
|
export function ValidationPanel({ npcConfig, dialogueConfig }: ValidationPanelProps) {
|
||||||
const npcErrors = validateNPCConfiguration(npcConfig);
|
const npcErrors = validateNPCConfiguration(npcConfig);
|
||||||
const dialogueErrors = dialogueConfig ? validateDialogueConfiguration(dialogueConfig) : [];
|
const dialogueErrors = dialogueConfig ? validateDialogueConfiguration(dialogueConfig) : [];
|
||||||
|
|
||||||
const allErrors = [...npcErrors, ...dialogueErrors];
|
const allErrors = [...npcErrors, ...dialogueErrors];
|
||||||
const summary = getValidationSummary(allErrors);
|
const summary = getValidationSummary(allErrors);
|
||||||
|
|
||||||
const ErrorItem: React.FC<{ error: ValidationError }> = ({ error }) => (
|
function ErrorItem({ error }: { error: ValidationError }) {
|
||||||
|
return (
|
||||||
<div className={`flex items-start space-x-2 p-2 rounded ${
|
<div className={`flex items-start space-x-2 p-2 rounded ${
|
||||||
error.severity === 'error' ? 'bg-red-50 text-red-800' : 'bg-yellow-50 text-yellow-800'
|
error.severity === 'error' ? 'bg-red-50 text-red-800' : 'bg-yellow-50 text-yellow-800'
|
||||||
}`}>
|
}`}>
|
||||||
@@ -30,7 +30,8 @@ export const ValidationPanel: React.FC<ValidationPanelProps> = ({ npcConfig, dia
|
|||||||
<p className="text-xs">{error.message}</p>
|
<p className="text-xs">{error.message}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (allErrors.length === 0) {
|
if (allErrors.length === 0) {
|
||||||
return (
|
return (
|
||||||
@@ -123,4 +124,4 @@ export const ValidationPanel: React.FC<ValidationPanelProps> = ({ npcConfig, dia
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
Reference in New Issue
Block a user