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:
natreex
2026-03-22 22:37:31 -04:00
parent e8aaef108b
commit 64ed90d993
229 changed files with 15091 additions and 21289 deletions

View File

@@ -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>
))
}