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