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,34 +1,32 @@
|
||||
import {ChapterListProps, ChapterProps} from "@/lib/models/Chapter";
|
||||
import {RefObject, useContext, useEffect, useRef, useState} from "react";
|
||||
import System from "@/lib/models/System";
|
||||
import {BookContext} from "@/context/BookContext";
|
||||
import {AlertContext} from "@/context/AlertContext";
|
||||
import {ChapterContext} from "@/context/ChapterContext";
|
||||
import {SessionContext} from "@/context/SessionContext";
|
||||
import {faSheetPlastic} from "@fortawesome/free-solid-svg-icons";
|
||||
import ListItem from "@/components/ListItem";
|
||||
import AlertBox from "@/components/AlertBox";
|
||||
import {useTranslations} from "next-intl";
|
||||
import InlineAddInput from "@/components/form/InlineAddInput";
|
||||
import {LangContext} from "@/context/LangContext";
|
||||
import OfflineContext, {OfflineContextType} from "@/context/OfflineContext";
|
||||
import {LocalSyncQueueContext, LocalSyncQueueContextProps} from "@/context/SyncQueueContext";
|
||||
import {BooksSyncContext, BooksSyncContextProps} from "@/context/BooksSyncContext";
|
||||
import {SyncedBook} from "@/lib/models/SyncedBook";
|
||||
import {ChapterListProps} from "@/lib/types/chapter";
|
||||
import React, {useContext, useEffect, useRef, useState} from "react";
|
||||
import {apiDelete, apiGet, apiPost} from '@/lib/api/client';
|
||||
import {isDesktop} from '@/lib/configs';
|
||||
import * as tauri from '@/lib/tauri';
|
||||
import OfflineContext, {OfflineContextType} from '@/context/OfflineContext';
|
||||
import {BookContext, BookContextProps} from "@/context/BookContext";
|
||||
import {AlertContext, AlertContextProps} from "@/context/AlertContext";
|
||||
import {ChapterContext, ChapterContextProps} from "@/context/ChapterContext";
|
||||
import {SessionContext, SessionContextProps} from "@/context/SessionContext";
|
||||
import {useRouter} from "@/lib/navigation";
|
||||
import {FileText} from "lucide-react";
|
||||
import ListItem from "@/components/ui/ListItem";
|
||||
import AlertBox from "@/components/ui/AlertBox";
|
||||
import {useTranslations} from '@/lib/i18n';
|
||||
import InlineAddInput from "@/components/form/InlineAddInput";
|
||||
import {LangContext, LangContextProps} from "@/context/LangContext";
|
||||
|
||||
export default function ScribeChapterComponent() {
|
||||
const t = useTranslations();
|
||||
const {lang} = useContext(LangContext);
|
||||
const {isCurrentlyOffline} = useContext<OfflineContextType>(OfflineContext);
|
||||
const {addToQueue} = useContext<LocalSyncQueueContextProps>(LocalSyncQueueContext);
|
||||
const {localSyncedBooks} = useContext<BooksSyncContextProps>(BooksSyncContext);
|
||||
|
||||
const {book} = useContext(BookContext);
|
||||
const {chapter, setChapter} = useContext(ChapterContext);
|
||||
const {errorMessage, successMessage} = useContext(AlertContext);
|
||||
const {session} = useContext(SessionContext);
|
||||
const {lang}: LangContextProps = useContext<LangContextProps>(LangContext);
|
||||
|
||||
const {book}: BookContextProps = useContext<BookContextProps>(BookContext);
|
||||
const {chapter}: ChapterContextProps = useContext<ChapterContextProps>(ChapterContext);
|
||||
const {errorMessage, successMessage}: AlertContextProps = useContext<AlertContextProps>(AlertContext);
|
||||
const {session}: SessionContextProps = useContext<SessionContextProps>(SessionContext);
|
||||
const userToken: string = session?.accessToken ? session?.accessToken : '';
|
||||
const {isCurrentlyOffline}: OfflineContextType = useContext<OfflineContextType>(OfflineContext);
|
||||
const router = useRouter();
|
||||
|
||||
const [chapters, setChapters] = useState<ChapterListProps[]>([])
|
||||
|
||||
@@ -38,12 +36,13 @@ export default function ScribeChapterComponent() {
|
||||
const [deleteConfirmationMessage, setDeleteConfirmationMessage] = useState<boolean>(false);
|
||||
const [removeChapterId, setRemoveChapterId] = useState<string>('');
|
||||
|
||||
const chapterRefs: RefObject<Map<string, HTMLDivElement>> = useRef<Map<string, HTMLDivElement>>(new Map());
|
||||
const scrollContainerRef: RefObject<HTMLUListElement | null> = useRef<HTMLUListElement>(null);
|
||||
const chapterRefs: React.RefObject<Map<string, HTMLDivElement>> = useRef<Map<string, HTMLDivElement>>(new Map());
|
||||
const scrollContainerRef: React.RefObject<HTMLUListElement | null> = useRef<HTMLUListElement>(null);
|
||||
|
||||
useEffect((): void => {
|
||||
if (book)
|
||||
getChapterList().then();
|
||||
if (book) {
|
||||
getChapterList().then();
|
||||
}
|
||||
}, [book]);
|
||||
|
||||
useEffect((): void => {
|
||||
@@ -52,16 +51,16 @@ export default function ScribeChapterComponent() {
|
||||
|
||||
useEffect((): void => {
|
||||
if (chapter?.chapterId && scrollContainerRef.current) {
|
||||
setTimeout(():void => {
|
||||
setTimeout((): void => {
|
||||
const element: HTMLDivElement | undefined = chapterRefs.current.get(chapter.chapterId);
|
||||
const container: HTMLUListElement | null = scrollContainerRef.current;
|
||||
|
||||
if (element && container) {
|
||||
const containerRect:DOMRect = container.getBoundingClientRect();
|
||||
const elementRect:DOMRect = element.getBoundingClientRect();
|
||||
const containerRect: DOMRect = container.getBoundingClientRect();
|
||||
const elementRect: DOMRect = element.getBoundingClientRect();
|
||||
|
||||
const relativeTop:number = elementRect.top - containerRect.top + container.scrollTop;
|
||||
const scrollPosition:number = relativeTop - (containerRect.height / 2) + (elementRect.height / 2);
|
||||
const relativeTop: number = elementRect.top - containerRect.top + container.scrollTop;
|
||||
const scrollPosition: number = relativeTop - (containerRect.height / 2) + (elementRect.height / 2);
|
||||
|
||||
container.scrollTo({
|
||||
top: Math.max(0, scrollPosition),
|
||||
@@ -79,11 +78,11 @@ export default function ScribeChapterComponent() {
|
||||
|
||||
async function getChapterList(): Promise<void> {
|
||||
try {
|
||||
let response: ChapterListProps[]|null;
|
||||
if (isCurrentlyOffline() || book?.localBook){
|
||||
let response: ChapterListProps[];
|
||||
if (isDesktop && (isCurrentlyOffline() || book?.localBook)) {
|
||||
response = await tauri.getChapters(book?.bookId ?? '') as ChapterListProps[];
|
||||
} else {
|
||||
response = await System.authGetQueryToServer<ChapterListProps[]>(`book/chapters?id=${book?.bookId}`, userToken, lang);
|
||||
response = await apiGet<ChapterListProps[]>(`book/chapters?id=${book?.bookId}`, userToken, lang);
|
||||
}
|
||||
if (response) {
|
||||
setChapters(response);
|
||||
@@ -97,49 +96,22 @@ export default function ScribeChapterComponent() {
|
||||
}
|
||||
}
|
||||
|
||||
async function getChapter(chapterId: string): Promise<void> {
|
||||
const version: number = chapter?.chapterContent.version ? chapter?.chapterContent.version : 2;
|
||||
try {
|
||||
let response: ChapterProps | null
|
||||
if (isCurrentlyOffline() || book?.localBook) {
|
||||
response = await tauri.getWholeChapter(chapterId, version, book?.bookId ?? '');
|
||||
} else {
|
||||
response = await System.authGetQueryToServer<ChapterProps>(`chapter/whole`, userToken, lang, {
|
||||
bookid: book?.bookId,
|
||||
id: chapterId,
|
||||
version: version,
|
||||
});
|
||||
}
|
||||
if (!response) {
|
||||
errorMessage(t("scribeChapterComponent.errorFetchChapter"));
|
||||
return;
|
||||
}
|
||||
setChapter(response);
|
||||
} catch (e: unknown) {
|
||||
if (e instanceof Error) {
|
||||
errorMessage(e.message);
|
||||
} else {
|
||||
errorMessage(t("scribeChapterComponent.errorFetchChapter"));
|
||||
}
|
||||
}
|
||||
function navigateToChapter(chapterId: string): void {
|
||||
router.push(`/book/${book?.bookId}/chapter/${chapterId}`);
|
||||
}
|
||||
|
||||
|
||||
async function handleChapterUpdate(chapterId: string, title: string, chapterOrder: number): Promise<void> {
|
||||
try {
|
||||
let response: boolean;
|
||||
const updateData = {
|
||||
chapterId: chapterId,
|
||||
chapterOrder: chapterOrder,
|
||||
title: title,
|
||||
};
|
||||
if (isCurrentlyOffline() || book?.localBook) {
|
||||
response = await tauri.updateChapter(updateData.chapterId, updateData.title, updateData.chapterOrder);
|
||||
if (isDesktop && (isCurrentlyOffline() || book?.localBook)) {
|
||||
response = await tauri.updateChapter(chapterId, title, chapterOrder);
|
||||
} else {
|
||||
response = await System.authPostToServer<boolean>('chapter/update', updateData, userToken, lang);
|
||||
|
||||
if (localSyncedBooks.find((syncedBook: SyncedBook): boolean => syncedBook.id === book?.bookId)) {
|
||||
addToQueue('update_chapter', {data: updateData});
|
||||
}
|
||||
response = await apiPost<boolean>('chapter/update', {
|
||||
chapterId: chapterId,
|
||||
chapterOrder: chapterOrder,
|
||||
title: title,
|
||||
}, userToken, lang);
|
||||
}
|
||||
if (!response) {
|
||||
errorMessage(t("scribeChapterComponent.errorChapterUpdate"));
|
||||
@@ -172,20 +144,13 @@ export default function ScribeChapterComponent() {
|
||||
async function handleDeleteChapter(): Promise<void> {
|
||||
try {
|
||||
setDeleteConfirmationMessage(false);
|
||||
let response:boolean = false;
|
||||
const deletedAt: number = System.timeStampInSeconds();
|
||||
if (isCurrentlyOffline() || book?.localBook) {
|
||||
response = await tauri.removeChapter(removeChapterId, book?.bookId ?? '', deletedAt);
|
||||
let response: boolean;
|
||||
if (isDesktop && (isCurrentlyOffline() || book?.localBook)) {
|
||||
response = await tauri.removeChapter(removeChapterId, book?.bookId ?? '', Date.now());
|
||||
} else {
|
||||
response = await System.authDeleteToServer<boolean>('chapter/remove', {
|
||||
response = await apiDelete<boolean>('chapter/remove', {
|
||||
chapterId: removeChapterId,
|
||||
bookId: book?.bookId,
|
||||
deletedAt,
|
||||
}, userToken, lang);
|
||||
|
||||
if (localSyncedBooks.find((syncedBook: SyncedBook): boolean => syncedBook.id === book?.bookId)) {
|
||||
addToQueue('remove_chapter', {data: {chapterId: removeChapterId, bookId: book?.bookId, deletedAt}});
|
||||
}
|
||||
}
|
||||
if (!response) {
|
||||
errorMessage(t("scribeChapterComponent.errorChapterDelete"));
|
||||
@@ -209,26 +174,21 @@ export default function ScribeChapterComponent() {
|
||||
errorMessage(t("scribeChapterComponent.errorChapterNameRequired"));
|
||||
return;
|
||||
}
|
||||
const chapterTitle: string = chapterOrder >= 0 ? newChapterName : book?.title as string;
|
||||
const chapterTitle: string = chapterOrder >= 0 ? newChapterName : (book?.title ?? '');
|
||||
try {
|
||||
let chapterId:string|null = null;
|
||||
const addData = {
|
||||
bookId: book?.bookId,
|
||||
chapterOrder: chapterOrder,
|
||||
title: chapterTitle
|
||||
};
|
||||
if (isCurrentlyOffline() || book?.localBook){
|
||||
let chapterId: string;
|
||||
if (isDesktop && (isCurrentlyOffline() || book?.localBook)) {
|
||||
chapterId = await tauri.addChapter({
|
||||
bookId: addData.bookId ?? '',
|
||||
title: addData.title,
|
||||
chapterOrder: addData.chapterOrder,
|
||||
bookId: book?.bookId ?? '',
|
||||
title: chapterTitle,
|
||||
chapterOrder: chapterOrder,
|
||||
});
|
||||
} else {
|
||||
chapterId = await System.authPostToServer<string>('chapter/add', addData, userToken, lang);
|
||||
|
||||
if (localSyncedBooks.find((syncedBook: SyncedBook): boolean => syncedBook.id === book?.bookId)) {
|
||||
addToQueue('add_chapter', {data: {...addData, chapterId}});
|
||||
}
|
||||
chapterId = await apiPost<string>('chapter/add', {
|
||||
bookId: book?.bookId,
|
||||
chapterOrder: chapterOrder,
|
||||
title: chapterTitle
|
||||
}, userToken, lang);
|
||||
}
|
||||
if (!chapterId) {
|
||||
errorMessage(t("scribeChapterComponent.errorChapterSubmit", {chapterName: newChapterName}));
|
||||
@@ -242,7 +202,7 @@ export default function ScribeChapterComponent() {
|
||||
setChapters((prevState: ChapterListProps[]): ChapterListProps[] => {
|
||||
return [newChapter, ...prevState]
|
||||
})
|
||||
await getChapter(chapterId);
|
||||
navigateToChapter(chapterId);
|
||||
} catch (e: unknown) {
|
||||
if (e instanceof Error) {
|
||||
errorMessage(e.message);
|
||||
@@ -255,10 +215,7 @@ export default function ScribeChapterComponent() {
|
||||
return (
|
||||
<div className="flex-1 flex flex-col p-4 min-h-0">
|
||||
<div className="mb-4">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<div className="h-6 w-1 bg-primary rounded-full"></div>
|
||||
<h3 className="text-lg font-bold text-primary tracking-wide">{t("scribeChapterComponent.sheetHeading")}</h3>
|
||||
</div>
|
||||
<h3 className="text-sm font-semibold text-text-secondary uppercase tracking-wider mb-3">{t("scribeChapterComponent.sheetHeading")}</h3>
|
||||
<ul className="space-y-2">
|
||||
{
|
||||
chapters.filter((chap: ChapterListProps): boolean => {
|
||||
@@ -268,17 +225,17 @@ export default function ScribeChapterComponent() {
|
||||
const aOrder: number = a.chapterOrder ?? 0;
|
||||
const bOrder: number = b.chapterOrder ?? 0;
|
||||
return aOrder - bOrder;
|
||||
}).map((chap: ChapterListProps) => (
|
||||
}).map((chap: ChapterListProps): React.JSX.Element => (
|
||||
<div key={chap.chapterId}
|
||||
ref={(el): void => {
|
||||
ref={(el: HTMLDivElement | null): void => {
|
||||
if (el) {
|
||||
chapterRefs.current.set(chap.chapterId, el);
|
||||
} else {
|
||||
chapterRefs.current.delete(chap.chapterId);
|
||||
}
|
||||
}}>
|
||||
<ListItem icon={faSheetPlastic}
|
||||
onClick={(): Promise<void> => getChapter(chap.chapterId)}
|
||||
<ListItem icon={FileText}
|
||||
onClick={(): void => navigateToChapter(chap.chapterId)}
|
||||
selectedId={chapter?.chapterId ?? ''}
|
||||
id={chap.chapterId}
|
||||
text={chap.title}/>
|
||||
@@ -290,7 +247,7 @@ export default function ScribeChapterComponent() {
|
||||
return chap.chapterOrder !== undefined && chap.chapterOrder < 0;
|
||||
}).length === 0 &&
|
||||
<li onClick={(): Promise<void> => handleAddChapter(-1)}
|
||||
className="group p-3 bg-secondary/30 rounded-xl hover:bg-secondary cursor-pointer transition-all hover:shadow-md border border-secondary/30 hover:border-primary/30">
|
||||
className="group p-3 rounded-xl hover:bg-tertiary cursor-pointer transition-colors duration-150">
|
||||
<span
|
||||
className="text-sm font-medium text-muted group-hover:text-text-primary transition-colors">
|
||||
{t("scribeChapterComponent.createSheet")}
|
||||
@@ -301,10 +258,7 @@ export default function ScribeChapterComponent() {
|
||||
</div>
|
||||
|
||||
<div className="flex-1 flex flex-col mt-6 min-h-0">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<div className="h-6 w-1 bg-primary rounded-full"></div>
|
||||
<h3 className="text-lg font-bold text-primary tracking-wide">{t("scribeChapterComponent.chaptersHeading")}</h3>
|
||||
</div>
|
||||
<h3 className="text-sm font-semibold text-text-secondary uppercase tracking-wider mb-3">{t("scribeChapterComponent.chaptersHeading")}</h3>
|
||||
<ul ref={scrollContainerRef} className="flex-1 space-y-2 overflow-y-auto pr-2 min-h-0">
|
||||
{
|
||||
chapters.filter((chap: ChapterListProps): boolean => {
|
||||
@@ -314,22 +268,32 @@ export default function ScribeChapterComponent() {
|
||||
const aOrder: number = a.chapterOrder ?? 0;
|
||||
const bOrder: number = b.chapterOrder ?? 0;
|
||||
return aOrder - bOrder;
|
||||
}).map((chap: ChapterListProps) => (
|
||||
}).map((chap: ChapterListProps): React.JSX.Element => (
|
||||
<div key={chap.chapterId}
|
||||
ref={(el): void => {
|
||||
ref={(el: HTMLDivElement | null): void => {
|
||||
if (el) {
|
||||
chapterRefs.current.set(chap.chapterId, el);
|
||||
} else {
|
||||
chapterRefs.current.delete(chap.chapterId);
|
||||
}
|
||||
}}>
|
||||
<ListItem onClick={(): Promise<void> => getChapter(chap.chapterId)}
|
||||
<ListItem onClick={(): void => navigateToChapter(chap.chapterId)}
|
||||
isEditable={true}
|
||||
handleUpdate={handleChapterUpdate}
|
||||
handleDelete={handleDeleteConfirmation}
|
||||
selectedId={chapter?.chapterId ?? ''}
|
||||
id={chap.chapterId} text={chap.title}
|
||||
numericalIdentifier={chap.chapterOrder}/>
|
||||
numericalIdentifier={chap.chapterOrder}
|
||||
onReorder={(chapterId: string, newOrder: number): void => {
|
||||
setChapters((previousChapters: ChapterListProps[]): ChapterListProps[] =>
|
||||
previousChapters.map((chapter: ChapterListProps): ChapterListProps =>
|
||||
chapter.chapterId === chapterId ? {
|
||||
...chapter,
|
||||
chapterOrder: newOrder
|
||||
} : chapter
|
||||
)
|
||||
);
|
||||
}}/>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user