refacto react component

This commit is contained in:
Matthieu
2025-08-11 22:30:36 +02:00
parent 43ee493f9e
commit 160aea6128
10 changed files with 42 additions and 43 deletions

View File

@@ -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 },

View File

@@ -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>
);
};
}

View File

@@ -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>
);
};
}

View File

@@ -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>
);
};
}

View File

@@ -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>
);
};
}

View File

@@ -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>
);
};
}

View File

@@ -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>
);
};
}

View File

@@ -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>
);
};
}

View File

@@ -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>
);
};
}

View File

@@ -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'
}`}>
@@ -31,6 +31,7 @@ export const ValidationPanel: React.FC<ValidationPanelProps> = ({ npcConfig, dia
</div>
</div>
);
}
if (allErrors.length === 0) {
return (
@@ -123,4 +124,4 @@ export const ValidationPanel: React.FC<ValidationPanelProps> = ({ npcConfig, dia
</div>
</div>
);
};
}