Remove unused components and models for improved maintainability
- Deleted redundant components (`AddActionButton`, `AlertBox`, `AlertStack`, `BackButton`, `CancelButton`, and `CollapsableArea`) and related files. - Removed unused models (`Book`, `BookSerie`, `BookTables`, `Character`, and `Chapter`) to reduce codebase clutter. - Updated project structure and references to reflect these removals.
This commit is contained in:
@@ -1,30 +1,63 @@
|
||||
'use client'
|
||||
import React, {ChangeEvent, forwardRef, useContext, useEffect, useImperativeHandle, useState} from "react";
|
||||
import {BookContext} from "@/context/BookContext";
|
||||
import {SessionContext} from "@/context/SessionContext";
|
||||
import {AlertContext} from "@/context/AlertContext";
|
||||
import {LangContext} from "@/context/LangContext";
|
||||
import System from "@/lib/models/System";
|
||||
import {QuillSenseSettingsProps} from "@/lib/models/QuillSenseSettings";
|
||||
import {useTranslations} from "next-intl";
|
||||
import ToggleSwitch from "@/components/form/ToggleSwitch";
|
||||
import TexteAreaInput from "@/components/form/TexteAreaInput";
|
||||
import {BookContext, BookContextProps} from "@/context/BookContext";
|
||||
import {SessionContext, SessionContextProps} from "@/context/SessionContext";
|
||||
import {AlertContext, AlertContextProps} from "@/context/AlertContext";
|
||||
import {LangContext, LangContextProps} from "@/context/LangContext";
|
||||
import {apiGet, apiPost, apiPut} from "@/lib/api/client";
|
||||
import {QuillSenseSettingsProps} from "@/lib/types/quillsense";
|
||||
import {GuideLineAI} from "@/lib/types/book";
|
||||
import {useTranslations} from '@/lib/i18n';
|
||||
import TextAreaInput from "@/components/form/TextAreaInput";
|
||||
import TextInput from "@/components/form/TextInput";
|
||||
import SelectBox from "@/components/form/SelectBox";
|
||||
import InputField from "@/components/form/InputField";
|
||||
import {faMagicWandSparkles, faToggleOn} from "@fortawesome/free-solid-svg-icons";
|
||||
import PulseLoader from '@/components/ui/PulseLoader';
|
||||
import {SettingRef} from "@/lib/types/settings";
|
||||
import {
|
||||
advancedDialogueTypes,
|
||||
advancedNarrativePersons,
|
||||
beginnerDialogueTypes,
|
||||
beginnerNarrativePersons,
|
||||
intermediateDialogueTypes,
|
||||
intermediateNarrativePersons,
|
||||
langues,
|
||||
verbalTime
|
||||
} from "@/lib/constants/story";
|
||||
|
||||
const QuillSenseSetting = forwardRef(function QuillSenseSetting(props, ref) {
|
||||
type QuillSenseTab = 'ghostwriter' | 'guideline';
|
||||
|
||||
interface QuillSenseSettingProps {
|
||||
toolEnabled?: boolean;
|
||||
}
|
||||
|
||||
const QuillSenseSetting = forwardRef<SettingRef, QuillSenseSettingProps>(function QuillSenseSetting({toolEnabled}: QuillSenseSettingProps, ref: React.ForwardedRef<SettingRef>): React.JSX.Element | null {
|
||||
const t = useTranslations();
|
||||
const {book, setBook} = useContext(BookContext);
|
||||
const {session} = useContext(SessionContext);
|
||||
const {errorMessage, successMessage} = useContext(AlertContext);
|
||||
const {lang} = useContext(LangContext);
|
||||
|
||||
const [quillsenseEnabled, setQuillsenseEnabled] = useState<boolean>(true);
|
||||
const [advancedPrompt, setAdvancedPrompt] = useState<string>('');
|
||||
const {book}: BookContextProps = useContext<BookContextProps>(BookContext);
|
||||
const {session}: SessionContextProps = useContext<SessionContextProps>(SessionContext);
|
||||
const {errorMessage, successMessage}: AlertContextProps = useContext<AlertContextProps>(AlertContext);
|
||||
const {lang}: LangContextProps = useContext<LangContextProps>(LangContext);
|
||||
const bookId: string = book?.bookId ?? '';
|
||||
const userToken: string = session?.accessToken ?? '';
|
||||
const authorLevel: string = session.user?.writingLevel?.toString() ?? '1';
|
||||
|
||||
const [activeTab, setActiveTab] = useState<QuillSenseTab>('ghostwriter');
|
||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
handleSave
|
||||
|
||||
// GhostWriter state
|
||||
const [advancedPrompt, setAdvancedPrompt] = useState<string>('');
|
||||
|
||||
// Guideline AI state
|
||||
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>('');
|
||||
const [themes, setThemes] = useState<string>('');
|
||||
|
||||
useImperativeHandle(ref, (): SettingRef => ({
|
||||
handleSave: activeTab === 'ghostwriter' ? handleSaveGhostWriter : handleSaveGuideline
|
||||
}));
|
||||
|
||||
useEffect((): void => {
|
||||
@@ -32,97 +65,222 @@ const QuillSenseSetting = forwardRef(function QuillSenseSetting(props, ref) {
|
||||
fetchQuillSenseSettings();
|
||||
}
|
||||
}, [book?.bookId]);
|
||||
|
||||
useEffect((): void => {
|
||||
if (activeTab === 'guideline' && !isLoading) {
|
||||
fetchAIGuideline();
|
||||
}
|
||||
}, [activeTab]);
|
||||
|
||||
async function fetchQuillSenseSettings(): Promise<void> {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const settings: QuillSenseSettingsProps = await System.authGetQueryToServer<QuillSenseSettingsProps>(
|
||||
const settings: QuillSenseSettingsProps = await apiGet<QuillSenseSettingsProps>(
|
||||
'book/quillsense-settings',
|
||||
session.accessToken,
|
||||
lang,
|
||||
{bookId: book?.bookId}
|
||||
);
|
||||
setQuillsenseEnabled(settings.quillsenseEnabled);
|
||||
setAdvancedPrompt(settings.advancedPrompt ?? '');
|
||||
} catch (e: unknown) {
|
||||
if (e instanceof Error) {
|
||||
errorMessage(e.message);
|
||||
} else {
|
||||
errorMessage(t('quillsenseSetting.unknownError'));
|
||||
}
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSave(): Promise<void> {
|
||||
|
||||
async function fetchAIGuideline(): Promise<void> {
|
||||
try {
|
||||
const updateResult: boolean = await System.authPutToServer<boolean>(
|
||||
const response: GuideLineAI = await apiGet<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 handleSaveGhostWriter(): Promise<void> {
|
||||
try {
|
||||
const updateResult: boolean = await apiPut<boolean>(
|
||||
'book/quillsense-settings',
|
||||
{
|
||||
bookId: book?.bookId,
|
||||
quillsenseEnabled: quillsenseEnabled,
|
||||
advancedPrompt: advancedPrompt
|
||||
},
|
||||
session.accessToken,
|
||||
lang
|
||||
);
|
||||
if (updateResult) {
|
||||
successMessage(t('quillSenseSetting.successSave'));
|
||||
// Mettre a jour le contexte du livre
|
||||
if (setBook && book) {
|
||||
setBook({...book, quillsenseEnabled: quillsenseEnabled});
|
||||
}
|
||||
successMessage(t('quillsenseSetting.saveSuccess'));
|
||||
} else {
|
||||
errorMessage(t('quillSenseSetting.errorSave'));
|
||||
errorMessage(t('quillsenseSetting.saveError'));
|
||||
}
|
||||
} catch (e: unknown) {
|
||||
if (e instanceof Error) {
|
||||
errorMessage(e.message);
|
||||
} else {
|
||||
errorMessage(t('quillsenseSetting.unknownError'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSaveGuideline(): Promise<void> {
|
||||
try {
|
||||
const response: boolean = await apiPost<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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center p-8">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
|
||||
</div>
|
||||
);
|
||||
return <PulseLoader/>;
|
||||
}
|
||||
|
||||
if (!toolEnabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-6 p-4">
|
||||
<div className="bg-secondary/20 rounded-xl p-5 shadow-inner border border-secondary/30">
|
||||
<InputField
|
||||
icon={faToggleOn}
|
||||
fieldName={t('quillSenseSetting.enableLabel')}
|
||||
input={
|
||||
<ToggleSwitch
|
||||
checked={quillsenseEnabled}
|
||||
onChange={(checked: boolean): void => setQuillsenseEnabled(checked)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<p className="text-muted text-sm mt-2">
|
||||
{t('quillSenseSetting.enableDescription')}
|
||||
</p>
|
||||
<div className="space-y-6">
|
||||
<div className="flex gap-4 border-b border-secondary">
|
||||
<button
|
||||
className={`pb-2 text-sm font-medium transition-colors duration-150 ${
|
||||
activeTab === 'ghostwriter'
|
||||
? 'border-b-2 border-primary text-text-primary'
|
||||
: 'text-muted hover:text-text-primary'
|
||||
}`}
|
||||
onClick={(): void => setActiveTab('ghostwriter')}
|
||||
>
|
||||
GhostWriter
|
||||
</button>
|
||||
<button
|
||||
className={`pb-2 text-sm font-medium transition-colors duration-150 ${
|
||||
activeTab === 'guideline'
|
||||
? 'border-b-2 border-primary text-text-primary'
|
||||
: 'text-muted hover:text-text-primary'
|
||||
}`}
|
||||
onClick={(): void => setActiveTab('guideline')}
|
||||
>
|
||||
{t("bookSetting.guideLine")}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="bg-secondary/20 rounded-xl p-5 shadow-inner border border-secondary/30">
|
||||
<InputField
|
||||
icon={faMagicWandSparkles}
|
||||
fieldName={t('quillSenseSetting.advancedPromptLabel')}
|
||||
input={
|
||||
<TexteAreaInput
|
||||
value={advancedPrompt}
|
||||
setValue={(e: ChangeEvent<HTMLTextAreaElement>): void => setAdvancedPrompt(e.target.value)}
|
||||
placeholder={t('quillSenseSetting.advancedPromptPlaceholder')}
|
||||
|
||||
{activeTab === 'ghostwriter' && (
|
||||
<div className="space-y-4">
|
||||
<InputField
|
||||
fieldName={t('quillsenseSetting.advancedPrompt')}
|
||||
input={
|
||||
<TextAreaInput
|
||||
value={advancedPrompt}
|
||||
setValue={(e: ChangeEvent<HTMLTextAreaElement>): void => setAdvancedPrompt(e.target.value)}
|
||||
placeholder={t('quillsenseSetting.advancedPromptPlaceholder')}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<p className="text-muted text-xs">
|
||||
{t('quillsenseSetting.advancedPromptDescription')}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === 'guideline' && (
|
||||
<div className="space-y-4">
|
||||
<InputField fieldName={t("guideLineSetting.plotSummary")} input={
|
||||
<TextAreaInput
|
||||
value={plotSummary}
|
||||
setValue={(e: ChangeEvent<HTMLTextAreaElement>): void => setPlotSummary(e.target.value)}
|
||||
placeholder={t("guideLineSetting.plotSummaryPlaceholder")}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<p className="text-muted text-sm mt-2">
|
||||
{t('quillSenseSetting.advancedPromptHint')}
|
||||
</p>
|
||||
</div>
|
||||
}/>
|
||||
<InputField fieldName={t("guideLineSetting.toneAtmosphere")} input={
|
||||
<TextInput
|
||||
value={toneAtmosphere}
|
||||
setValue={(e: ChangeEvent<HTMLInputElement>): void => setToneAtmosphere(e.target.value)}
|
||||
placeholder={t("guideLineSetting.toneAtmospherePlaceholder")}
|
||||
/>
|
||||
}/>
|
||||
<InputField fieldName={t("guideLineSetting.themes")} input={
|
||||
<TextInput
|
||||
value={themes}
|
||||
setValue={(e: ChangeEvent<HTMLInputElement>): void => setThemes(e.target.value)}
|
||||
placeholder={t("guideLineSetting.themesPlaceholderQuill")}
|
||||
/>
|
||||
}/>
|
||||
<InputField fieldName={t("guideLineSetting.verbTense")} input={
|
||||
<SelectBox
|
||||
defaultValue={verbTense}
|
||||
onChangeCallBack={(event: ChangeEvent<HTMLSelectElement>): void => setVerbTense(event.target.value)}
|
||||
data={verbalTime}
|
||||
placeholder={t("guideLineSetting.verbTensePlaceholder")}
|
||||
/>
|
||||
}/>
|
||||
<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")}/>
|
||||
}/>
|
||||
<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")}/>
|
||||
}/>
|
||||
<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>
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user