- Removed unnecessary React imports. - Adjusted package.json scripts for Electron integration. - Updated components to replace Next.js-specific imports with Electron-compatible alternatives. - Minor tsconfig.json changes for better compatibility.
421 lines
20 KiB
TypeScript
421 lines
20 KiB
TypeScript
'use client'
|
|
import {ChangeEvent, forwardRef, useContext, useEffect, useImperativeHandle, useState} from 'react';
|
|
import System from '@/lib/models/System';
|
|
import {AlertContext} from "@/context/AlertContext";
|
|
import {BookContext} from '@/context/BookContext';
|
|
import {SessionContext} from "@/context/SessionContext";
|
|
import {GuideLine, GuideLineAI} from "@/lib/models/Book";
|
|
import TexteAreaInput from "@/components/form/TexteAreaInput";
|
|
import InputField from "@/components/form/InputField";
|
|
import TextInput from "@/components/form/TextInput";
|
|
import SelectBox from "@/components/form/SelectBox";
|
|
import {
|
|
advancedDialogueTypes,
|
|
advancedNarrativePersons,
|
|
beginnerDialogueTypes,
|
|
beginnerNarrativePersons,
|
|
intermediateDialogueTypes,
|
|
intermediateNarrativePersons,
|
|
langues,
|
|
verbalTime
|
|
} from "@/lib/models/Story";
|
|
import {useTranslations} from "next-intl";
|
|
import {LangContext} from "@/context/LangContext";
|
|
|
|
function GuideLineSetting(props: any, ref: any) {
|
|
const t = useTranslations();
|
|
const {lang} = useContext(LangContext);
|
|
const {book} = useContext(BookContext);
|
|
const {session} = useContext(SessionContext);
|
|
const userToken: string = session?.accessToken ? session?.accessToken : '';
|
|
const {errorMessage, successMessage} = useContext(AlertContext);
|
|
const bookId = book?.bookId as string;
|
|
const [activeTab, setActiveTab] = useState('personal');
|
|
const authorLevel: string = session.user?.writingLevel?.toString() ?? '1';
|
|
|
|
const [tone, setTone] = useState<string>('');
|
|
const [atmosphere, setAtmosphere] = useState<string>('');
|
|
const [writingStyle, setWritingStyle] = useState<string>('');
|
|
const [themes, setThemes] = useState<string>('');
|
|
const [symbolism, setSymbolism] = useState<string>('');
|
|
const [motifs, setMotifs] = useState<string>('');
|
|
const [narrativeVoice, setNarrativeVoice] = useState<string>('');
|
|
const [pacing, setPacing] = useState<string>('');
|
|
const [intendedAudience, setIntendedAudience] = useState<string>('');
|
|
const [keyMessages, setKeyMessages] = useState<string>('');
|
|
|
|
const [plotSummary, setPlotSummary] = useState<string>('');
|
|
const [narrativeType, setNarrativeType] = useState<string>('');
|
|
const [verbTense, setVerbTense] = useState<string>('');
|
|
const [dialogueType, setDialogueType] = useState<string>('');
|
|
const [toneAtmosphere, setToneAtmosphere] = useState<string>('');
|
|
const [language, setLanguage] = useState<string>('');
|
|
|
|
useEffect((): void => {
|
|
if (activeTab === 'personal') {
|
|
getGuideLine().then();
|
|
} else {
|
|
getAIGuideLine().then();
|
|
}
|
|
}, [activeTab]);
|
|
|
|
useImperativeHandle(ref, () => {
|
|
{
|
|
if (activeTab === 'personal') {
|
|
return {
|
|
handleSave: savePersonal
|
|
};
|
|
} else {
|
|
return {
|
|
handleSave: saveQuillSense
|
|
};
|
|
}
|
|
}
|
|
});
|
|
|
|
async function getAIGuideLine(): Promise<void> {
|
|
try {
|
|
const response: GuideLineAI = await System.authGetQueryToServer<GuideLineAI>(`book/ai/guideline`, userToken, lang, {id: bookId});
|
|
if (response) {
|
|
setPlotSummary(response.globalResume);
|
|
setVerbTense(response.verbeTense?.toString() || '');
|
|
setNarrativeType(response.narrativeType?.toString() || '');
|
|
setDialogueType(response.dialogueType?.toString() || '');
|
|
setToneAtmosphere(response.atmosphere);
|
|
setLanguage(response.langue?.toString() || '');
|
|
setThemes(response.themes);
|
|
}
|
|
} catch (e: unknown) {
|
|
if (e instanceof Error) {
|
|
errorMessage(e.message);
|
|
} else {
|
|
errorMessage(t("guideLineSetting.errorUnknown"));
|
|
}
|
|
}
|
|
}
|
|
|
|
async function getGuideLine(): Promise<void> {
|
|
try {
|
|
const response: GuideLine =
|
|
await System.authGetQueryToServer<GuideLine>(
|
|
`book/guide-line`,
|
|
userToken,
|
|
lang,
|
|
{id: bookId},
|
|
);
|
|
if (response) {
|
|
setTone(response.tone);
|
|
setAtmosphere(response.atmosphere);
|
|
setWritingStyle(response.writingStyle);
|
|
setThemes(response.themes);
|
|
setSymbolism(response.symbolism);
|
|
setMotifs(response.motifs);
|
|
setNarrativeVoice(response.narrativeVoice);
|
|
setPacing(response.pacing);
|
|
setIntendedAudience(response.intendedAudience);
|
|
setKeyMessages(response.keyMessages);
|
|
}
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
errorMessage(error.message);
|
|
} else {
|
|
errorMessage(t("guideLineSetting.errorUnknown"));
|
|
}
|
|
}
|
|
}
|
|
|
|
async function savePersonal(): Promise<void> {
|
|
try {
|
|
const response: boolean =
|
|
await System.authPostToServer<boolean>(
|
|
'book/guide-line',
|
|
{
|
|
bookId: bookId,
|
|
tone: tone,
|
|
atmosphere: atmosphere,
|
|
writingStyle: writingStyle,
|
|
themes: themes,
|
|
symbolism: symbolism,
|
|
motifs: motifs,
|
|
narrativeVoice: narrativeVoice,
|
|
pacing: pacing,
|
|
intendedAudience: intendedAudience,
|
|
keyMessages: keyMessages,
|
|
},
|
|
userToken,
|
|
lang,
|
|
);
|
|
if (!response) {
|
|
errorMessage(t("guideLineSetting.saveError"));
|
|
return;
|
|
}
|
|
successMessage(t("guideLineSetting.saveSuccess"));
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
errorMessage(error.message);
|
|
} else {
|
|
errorMessage(t("guideLineSetting.errorUnknown"));
|
|
}
|
|
}
|
|
}
|
|
|
|
async function saveQuillSense(): Promise<void> {
|
|
try {
|
|
const response: boolean = await System.authPostToServer<boolean>(
|
|
'quillsense/book/guide-line',
|
|
{
|
|
bookId: bookId,
|
|
plotSummary: plotSummary,
|
|
verbTense: verbTense,
|
|
narrativeType: narrativeType,
|
|
dialogueType: dialogueType,
|
|
toneAtmosphere: toneAtmosphere,
|
|
language: language,
|
|
themes: themes,
|
|
},
|
|
userToken,
|
|
lang,
|
|
);
|
|
if (response) {
|
|
successMessage(t("guideLineSetting.saveSuccess"));
|
|
} else {
|
|
errorMessage(t("guideLineSetting.saveError"));
|
|
}
|
|
} catch (e: unknown) {
|
|
if (e instanceof Error) {
|
|
errorMessage(e.message);
|
|
} else {
|
|
errorMessage(t("guideLineSetting.errorUnknown"));
|
|
}
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<div className="flex gap-2 border-b border-secondary/50 mb-6">
|
|
<button
|
|
className={`px-5 py-2.5 font-medium rounded-t-xl transition-all duration-200 ${
|
|
activeTab === 'personal'
|
|
? 'border-b-2 border-primary text-primary bg-primary/10 shadow-md'
|
|
: 'text-text-secondary hover:text-text-primary hover:bg-secondary/30'
|
|
}`}
|
|
onClick={(): void => setActiveTab('personal')}
|
|
>
|
|
{t("guideLineSetting.personal")}
|
|
</button>
|
|
<button
|
|
className={`px-5 py-2.5 font-medium rounded-t-xl transition-all duration-200 ${
|
|
activeTab === 'quillsense'
|
|
? 'border-b-2 border-primary text-primary bg-primary/10 shadow-md'
|
|
: 'text-text-secondary hover:text-text-primary hover:bg-secondary/30'
|
|
}`}
|
|
onClick={() => setActiveTab('quillsense')}
|
|
>
|
|
{t("guideLineSetting.quillsense")}
|
|
</button>
|
|
</div>
|
|
|
|
{activeTab === 'personal' && (
|
|
<div className="space-y-4">
|
|
<div
|
|
className="bg-tertiary/90 backdrop-blur-sm rounded-xl p-5 border border-secondary/50 shadow-md">
|
|
<InputField fieldName={t("guideLineSetting.tone")} input={
|
|
<TexteAreaInput
|
|
value={tone}
|
|
setValue={(e: ChangeEvent<HTMLTextAreaElement>) => setTone(e.target.value)}
|
|
placeholder={t("guideLineSetting.tonePlaceholder")}
|
|
/>
|
|
}/>
|
|
</div>
|
|
|
|
<div
|
|
className="bg-tertiary/90 backdrop-blur-sm rounded-xl p-5 border border-secondary/50 shadow-md">
|
|
<InputField fieldName={t("guideLineSetting.atmosphere")} input={
|
|
<TexteAreaInput
|
|
value={atmosphere}
|
|
setValue={(e: ChangeEvent<HTMLTextAreaElement>) => setAtmosphere(e.target.value)}
|
|
placeholder={t("guideLineSetting.atmospherePlaceholder")}
|
|
/>
|
|
}/>
|
|
</div>
|
|
|
|
<div
|
|
className="bg-tertiary/90 backdrop-blur-sm rounded-xl p-5 border border-secondary/50 shadow-md">
|
|
<InputField fieldName={t("guideLineSetting.writingStyle")} input={
|
|
<TexteAreaInput
|
|
value={writingStyle}
|
|
setValue={(e: ChangeEvent<HTMLTextAreaElement>): void => setWritingStyle(e.target.value)}
|
|
placeholder={t("guideLineSetting.writingStylePlaceholder")}
|
|
/>
|
|
}/>
|
|
</div>
|
|
|
|
<div
|
|
className="bg-tertiary/90 backdrop-blur-sm rounded-xl p-5 border border-secondary/50 shadow-md">
|
|
<InputField fieldName={t("guideLineSetting.themes")} input={
|
|
<TexteAreaInput
|
|
value={themes}
|
|
setValue={(e: ChangeEvent<HTMLTextAreaElement>): void => setThemes(e.target.value)}
|
|
placeholder={t("guideLineSetting.themesPlaceholder")}
|
|
/>
|
|
}/>
|
|
</div>
|
|
|
|
<div
|
|
className="bg-tertiary/90 backdrop-blur-sm rounded-xl p-5 border border-secondary/50 shadow-md">
|
|
<InputField fieldName={t("guideLineSetting.symbolism")} input={
|
|
<TexteAreaInput
|
|
value={symbolism}
|
|
setValue={(e: ChangeEvent<HTMLTextAreaElement>): void => setSymbolism(e.target.value)}
|
|
placeholder={t("guideLineSetting.symbolismPlaceholder")}
|
|
/>
|
|
}/>
|
|
</div>
|
|
|
|
<div
|
|
className="bg-tertiary/90 backdrop-blur-sm rounded-xl p-5 border border-secondary/50 shadow-md">
|
|
<InputField fieldName={t("guideLineSetting.motifs")} input={
|
|
<TexteAreaInput
|
|
value={motifs}
|
|
setValue={(e: ChangeEvent<HTMLTextAreaElement>): void => setMotifs(e.target.value)}
|
|
placeholder={t("guideLineSetting.motifsPlaceholder")}
|
|
/>
|
|
}/>
|
|
</div>
|
|
|
|
<div
|
|
className="bg-tertiary/90 backdrop-blur-sm rounded-xl p-5 border border-secondary/50 shadow-md">
|
|
<InputField fieldName={t("guideLineSetting.narrativeVoice")} input={
|
|
<TexteAreaInput
|
|
value={narrativeVoice}
|
|
setValue={(e: ChangeEvent<HTMLTextAreaElement>): void => setNarrativeVoice(e.target.value)}
|
|
placeholder={t("guideLineSetting.narrativeVoicePlaceholder")}
|
|
/>
|
|
}/>
|
|
</div>
|
|
|
|
<div
|
|
className="bg-tertiary/90 backdrop-blur-sm rounded-xl p-5 border border-secondary/50 shadow-md">
|
|
<InputField fieldName={t("guideLineSetting.pacing")} input={
|
|
<TexteAreaInput
|
|
value={pacing}
|
|
setValue={(e: ChangeEvent<HTMLTextAreaElement>): void => setPacing(e.target.value)}
|
|
placeholder={t("guideLineSetting.pacingPlaceholder")}
|
|
/>
|
|
}/>
|
|
</div>
|
|
|
|
<div
|
|
className="bg-tertiary/90 backdrop-blur-sm rounded-xl p-5 border border-secondary/50 shadow-md">
|
|
<InputField fieldName={t("guideLineSetting.intendedAudience")} input={
|
|
<TexteAreaInput
|
|
value={intendedAudience}
|
|
setValue={(e: ChangeEvent<HTMLTextAreaElement>): void => setIntendedAudience(e.target.value)}
|
|
placeholder={t("guideLineSetting.intendedAudiencePlaceholder")}
|
|
/>
|
|
}/>
|
|
</div>
|
|
|
|
<div
|
|
className="bg-tertiary/90 backdrop-blur-sm rounded-xl p-5 border border-secondary/50 shadow-md">
|
|
<InputField fieldName={t("guideLineSetting.keyMessages")} input={
|
|
<TexteAreaInput
|
|
value={keyMessages}
|
|
setValue={(e: ChangeEvent<HTMLTextAreaElement>): void => setKeyMessages(e.target.value)}
|
|
placeholder={t("guideLineSetting.keyMessagesPlaceholder")}
|
|
/>
|
|
}/>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{activeTab === 'quillsense' && (
|
|
<div className="space-y-4">
|
|
<div
|
|
className="bg-tertiary/90 backdrop-blur-sm rounded-xl p-5 border border-secondary/50 shadow-md">
|
|
<InputField fieldName={t("guideLineSetting.plotSummary")} input={
|
|
<TexteAreaInput
|
|
value={plotSummary}
|
|
setValue={(e: ChangeEvent<HTMLTextAreaElement>): void => setPlotSummary(e.target.value)}
|
|
placeholder={t("guideLineSetting.plotSummaryPlaceholder")}
|
|
/>
|
|
}/>
|
|
</div>
|
|
|
|
<div
|
|
className="bg-tertiary/90 backdrop-blur-sm rounded-xl p-5 border border-secondary/50 shadow-md">
|
|
<InputField fieldName={t("guideLineSetting.toneAtmosphere")} input={
|
|
<TextInput
|
|
value={toneAtmosphere}
|
|
setValue={(e: ChangeEvent<HTMLInputElement>): void => setToneAtmosphere(e.target.value)}
|
|
placeholder={t("guideLineSetting.toneAtmospherePlaceholder")}
|
|
/>
|
|
}/>
|
|
</div>
|
|
|
|
<div
|
|
className="bg-tertiary/90 backdrop-blur-sm rounded-xl p-5 border border-secondary/50 shadow-md">
|
|
<InputField fieldName={t("guideLineSetting.themes")} input={
|
|
<TextInput
|
|
value={themes}
|
|
setValue={(e: ChangeEvent<HTMLInputElement>) => setThemes(e.target.value)}
|
|
placeholder={t("guideLineSetting.themesPlaceholderQuill")}
|
|
/>
|
|
}/>
|
|
</div>
|
|
<div
|
|
className="bg-tertiary/90 backdrop-blur-sm rounded-xl p-5 border border-secondary/50 shadow-md">
|
|
<InputField fieldName={t("guideLineSetting.verbTense")} input={
|
|
<SelectBox
|
|
defaultValue={verbTense}
|
|
onChangeCallBack={(event: ChangeEvent<HTMLSelectElement>): void => setVerbTense(event.target.value)}
|
|
data={verbalTime}
|
|
placeholder={t("guideLineSetting.verbTensePlaceholder")}
|
|
/>
|
|
}/>
|
|
</div>
|
|
<div
|
|
className="bg-tertiary/90 backdrop-blur-sm rounded-xl p-5 border border-secondary/50 shadow-md">
|
|
<InputField fieldName={t("guideLineSetting.narrativeType")} input={
|
|
<SelectBox defaultValue={narrativeType} data={
|
|
authorLevel === '1'
|
|
? beginnerNarrativePersons
|
|
: authorLevel === '2'
|
|
? intermediateNarrativePersons
|
|
: advancedNarrativePersons
|
|
} onChangeCallBack={(event: ChangeEvent<HTMLSelectElement>): void => {
|
|
setNarrativeType(event.target.value)
|
|
}} placeholder={t("guideLineSetting.narrativeTypePlaceholder")}/>
|
|
}/>
|
|
</div>
|
|
|
|
<div
|
|
className="bg-tertiary/90 backdrop-blur-sm rounded-xl p-5 border border-secondary/50 shadow-md">
|
|
<InputField fieldName={t("guideLineSetting.dialogueType")} input={
|
|
<SelectBox defaultValue={dialogueType} data={authorLevel === '1'
|
|
? beginnerDialogueTypes
|
|
: authorLevel === '2'
|
|
? intermediateDialogueTypes
|
|
: advancedDialogueTypes}
|
|
onChangeCallBack={(event: ChangeEvent<HTMLSelectElement>) => {
|
|
setDialogueType(event.target.value)
|
|
}} placeholder={t("guideLineSetting.dialogueTypePlaceholder")}/>
|
|
}/>
|
|
</div>
|
|
|
|
<div
|
|
className="bg-tertiary/90 backdrop-blur-sm rounded-xl p-5 border border-secondary/50 shadow-md">
|
|
<InputField fieldName={t("guideLineSetting.language")} input={
|
|
<SelectBox defaultValue={language} data={langues}
|
|
onChangeCallBack={(event: ChangeEvent<HTMLSelectElement>) => {
|
|
setLanguage(event.target.value)
|
|
}} placeholder={t("guideLineSetting.languagePlaceholder")}/>
|
|
}/>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default forwardRef(GuideLineSetting); |