Add components for Act management and integrate Electron setup

This commit is contained in:
natreex
2025-11-16 11:00:04 -05:00
parent e192b6dcc2
commit 8167948881
97 changed files with 25378 additions and 3 deletions

View File

@@ -0,0 +1,421 @@
'use client'
import React, {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);