Add components for Act management and integrate Electron setup
This commit is contained in:
184
components/ScribeControllerBar.tsx
Normal file
184
components/ScribeControllerBar.tsx
Normal file
@@ -0,0 +1,184 @@
|
||||
import React, {useContext, useState} from "react";
|
||||
import {ChapterProps, chapterVersions} from "@/lib/models/Chapter";
|
||||
import {ChapterContext} from "@/context/ChapterContext";
|
||||
import {BookContext} from "@/context/BookContext";
|
||||
import System from "@/lib/models/System";
|
||||
import UserMenu from "@/components/UserMenu";
|
||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||
import {faGear, faGlobe, faHome} from "@fortawesome/free-solid-svg-icons";
|
||||
import {SelectBoxProps} from "@/shared/interface";
|
||||
import {AlertContext} from "@/context/AlertContext";
|
||||
import {SessionContext} from "@/context/SessionContext";
|
||||
import Book, {BookListProps} from "@/lib/models/Book";
|
||||
import Modal from "@/components/Modal";
|
||||
import BookSetting from "@/components/book/settings/BookSetting";
|
||||
import SelectBox from "@/components/form/SelectBox";
|
||||
import {useTranslations} from "next-intl";
|
||||
import {LangContext, LangContextProps} from "@/context/LangContext";
|
||||
import CreditCounter from "@/components/CreditMeters";
|
||||
import QuillSense from "@/lib/models/QuillSense";
|
||||
|
||||
export default function ScribeControllerBar() {
|
||||
const {chapter, setChapter} = useContext(ChapterContext);
|
||||
const {book, setBook} = useContext(BookContext);
|
||||
const {errorMessage} = useContext(AlertContext)
|
||||
const {session} = useContext(SessionContext);
|
||||
const t = useTranslations();
|
||||
const {lang, setLang} = useContext<LangContextProps>(LangContext)
|
||||
|
||||
const isGPTEnabled: boolean = QuillSense.isOpenAIEnabled(session);
|
||||
const isGemini: boolean = QuillSense.isOpenAIEnabled(session);
|
||||
const isAnthropic: boolean = QuillSense.isOpenAIEnabled(session);
|
||||
const isSubTierTwo: boolean = QuillSense.getSubLevel(session) >= 2;
|
||||
const hasAccess: boolean = (isGPTEnabled || isAnthropic || isGemini) || isSubTierTwo;
|
||||
|
||||
const [showSettingPanel, setShowSettingPanel] = useState<boolean>(false);
|
||||
|
||||
async function handleChapterVersionChanged(version: number) {
|
||||
try {
|
||||
const response: ChapterProps = await System.authGetQueryToServer<ChapterProps>(`chapter/whole`, session.accessToken, lang, {
|
||||
bookid: book?.bookId,
|
||||
id: chapter?.chapterId,
|
||||
version: version,
|
||||
});
|
||||
if (!response) {
|
||||
errorMessage(t("controllerBar.chapterNotFound"));
|
||||
return;
|
||||
}
|
||||
setChapter(response);
|
||||
} catch (e: unknown) {
|
||||
if (e instanceof Error) {
|
||||
errorMessage(e.message);
|
||||
} else {
|
||||
errorMessage(t("controllerBar.unknownChapterError"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getBook(bookId: string): Promise<void> {
|
||||
try {
|
||||
const response: BookListProps = await System.authGetQueryToServer<BookListProps>(`book/basic-information`, session.accessToken, lang, {
|
||||
id: bookId,
|
||||
});
|
||||
if (!response) {
|
||||
errorMessage(t("controllerBar.bookNotFound"));
|
||||
return;
|
||||
}
|
||||
setBook!!({
|
||||
bookId: response.id,
|
||||
type: response.type,
|
||||
title: response.title,
|
||||
subTitle: response.subTitle,
|
||||
summary: response.summary,
|
||||
publicationDate: response.desiredReleaseDate,
|
||||
desiredWordCount: response.desiredWordCount,
|
||||
totalWordCount: response.desiredWordCount,
|
||||
});
|
||||
} catch (e: unknown) {
|
||||
if (e instanceof Error) {
|
||||
errorMessage(e.message);
|
||||
} else {
|
||||
errorMessage(t("controllerBar.unknownBookError"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleLanguageChange(language: "fr" | "en"): void {
|
||||
System.setCookie('lang', language, 365);
|
||||
const newLang: "en" | "fr" | null = System.getCookie('lang') as "en" | "fr" | null;
|
||||
if (newLang) {
|
||||
setLang(language);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className="flex items-center justify-between px-6 py-3 bg-tertiary/90 backdrop-blur-sm border-b border-secondary/50 shadow-md">
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="flex items-center gap-2">
|
||||
{book && (
|
||||
<button onClick={(): void => setShowSettingPanel(true)}
|
||||
className="group p-2 rounded-lg text-muted hover:text-text-primary hover:bg-secondary/50 transition-all hover:scale-110">
|
||||
<FontAwesomeIcon icon={faGear}
|
||||
className={'w-5 h-5 transition-transform group-hover:rotate-90'}/>
|
||||
</button>
|
||||
)}
|
||||
{
|
||||
book && (
|
||||
<button onClick={(): void => {
|
||||
setBook && setBook(null)
|
||||
setChapter && setChapter(undefined)
|
||||
}}
|
||||
className="group p-2 rounded-lg text-muted hover:text-primary hover:bg-secondary/50 transition-all hover:scale-110">
|
||||
<FontAwesomeIcon icon={faHome}
|
||||
className={'w-5 h-5 transition-transform group-hover:scale-110'}/>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div className="min-w-[200px]">
|
||||
<SelectBox onChangeCallBack={(e) => getBook(e.target.value)}
|
||||
data={Book.booksToSelectBox(session.user?.books ?? [])} defaultValue={book?.bookId}
|
||||
placeholder={t("controllerBar.selectBook")}/>
|
||||
</div>
|
||||
{chapter && (
|
||||
<div className="min-w-[180px]">
|
||||
<SelectBox onChangeCallBack={(e) => handleChapterVersionChanged(parseInt(e.target.value))}
|
||||
data={chapterVersions.filter((version: SelectBoxProps): boolean => {
|
||||
return !(version.value === '1' && !hasAccess);
|
||||
}).map((version: SelectBoxProps) => {
|
||||
return {
|
||||
value: version.value.toString(),
|
||||
label: t(version.label)
|
||||
}
|
||||
})} defaultValue={chapter?.chapterContent.version.toString()}/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center space-x-4">
|
||||
{
|
||||
hasAccess &&
|
||||
<CreditCounter isCredit={isSubTierTwo}/>
|
||||
}
|
||||
<div
|
||||
className="flex items-center bg-secondary/50 rounded-xl overflow-hidden border border-secondary shadow-sm">
|
||||
<div className="flex items-center px-3 py-2 bg-dark-background/50 border-r border-secondary">
|
||||
<FontAwesomeIcon icon={faGlobe} className="w-4 h-4 text-primary"/>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => handleLanguageChange('fr')}
|
||||
className={`px-4 py-2 text-sm font-semibold transition-all ${
|
||||
lang === 'fr'
|
||||
? 'bg-primary text-text-primary shadow-md'
|
||||
: 'bg-transparent text-text-secondary hover:bg-secondary/50 hover:text-text-primary'
|
||||
}`}
|
||||
>
|
||||
FR
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleLanguageChange('en')}
|
||||
className={`px-4 py-2 text-sm font-semibold transition-all ${
|
||||
lang === 'en'
|
||||
? 'bg-primary text-text-primary shadow-md'
|
||||
: 'bg-transparent text-text-secondary hover:bg-secondary/50 hover:text-text-primary'
|
||||
}`}
|
||||
>
|
||||
EN
|
||||
</button>
|
||||
</div>
|
||||
<UserMenu/>
|
||||
</div>
|
||||
{
|
||||
showSettingPanel &&
|
||||
<Modal title={t("controllerBar.bookSettings")}
|
||||
size={'large'}
|
||||
onClose={() => setShowSettingPanel(false)}
|
||||
onConfirm={() => {
|
||||
}}
|
||||
children={<BookSetting/>}
|
||||
enableFooter={false}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user