diff --git a/src/app/api/reports/route.ts b/src/app/api/reports/route.ts
new file mode 100644
index 0000000..2cf1173
--- /dev/null
+++ b/src/app/api/reports/route.ts
@@ -0,0 +1,38 @@
+
+import { NextResponse } from 'next/server';
+
+export async function POST(request: Request) {
+ try {
+ const API_URL = process.env.NEXT_PUBLIC_API_URL;
+ const API_TOKEN = process.env.STRAPI_API_TOKEN;
+
+ const body = await request.json();
+
+ if (!API_URL || !API_TOKEN) {
+ return NextResponse.json({ message: 'Server configuration error' }, {status: 500});
+ }
+ try {
+ const response = await fetch(`${API_URL}/api/reports`, {
+ method: 'POST',
+ headers: {
+ Authorization: `Bearer ${API_TOKEN}`,
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(body),
+ });
+
+ const data = await response.json();
+
+ if (!response.ok) {
+ return NextResponse.json({ error: data }, { status: response.status });
+ }
+
+ return NextResponse.json({data: data}, {status: response.status});
+ } catch (error: any) {
+ NextResponse.json({message: 'Going to server error', error: error.message})
+ }
+ } catch (error: any) {
+ console.error('Error handling request:', error);
+ return NextResponse.json({ message: 'Internal Server Error', error: error.message }, { status: 500 });
+ }
+}
diff --git a/src/app/books/[bookId]/chapters/[chapterId]/page.tsx b/src/app/books/[bookId]/chapters/[chapterId]/page.tsx
index 6efbf42..36405af 100644
--- a/src/app/books/[bookId]/chapters/[chapterId]/page.tsx
+++ b/src/app/books/[bookId]/chapters/[chapterId]/page.tsx
@@ -1,5 +1,6 @@
import React from "react";
import NavigationButtons from "@/components/NavigationButtons";
+import ReportButton from "@/components/ReportButton";
import ChapterRenderer from "@/components/ChapterContentRenderer";
import { Chapter } from "@/lib/types";
import { fetchChapterByBookId, fetchGlossaryByBookId } from "@/lib/api";
@@ -50,6 +51,7 @@ export default async function ChapterPage(props: { params: paramsType}) {
+
);
}
\ No newline at end of file
diff --git a/src/components/ReportButton.tsx b/src/components/ReportButton.tsx
new file mode 100644
index 0000000..44631c9
--- /dev/null
+++ b/src/components/ReportButton.tsx
@@ -0,0 +1,128 @@
+"use client"
+import React, { useState, useRef } from "react";
+
+interface ReportButtonProps {
+ bookId: string;
+ chapterId: string;
+}
+async function createReport(
+ error_type: string,
+ details: string,
+ book_id: string,
+ chapter_id: string,
+) {
+ const payload = {
+ data:{
+ error_type: error_type,
+ details: details,
+ book: book_id,
+ chapter: chapter_id
+ }
+ }
+
+ const response = await fetch(
+ '/api/reports',
+ {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(payload)
+ }
+ )
+
+ if(!response.ok) {
+ throw new Error(`API request failed with status ${response.status}`)
+ }
+ return response.json()
+}
+const ReportButton: React.FC = ({ bookId, chapterId }) => {
+ const modalRef = useRef(null)
+ const [isOpen, setIsOpen] = useState(false)
+ const [errorType, setErrorType] = useState('')
+ const [details, setDetails] = useState('')
+ const handleSubmitReport = (event: React.FormEvent) => {
+ // Implement report submission here
+ event.preventDefault()
+ createReport(errorType,details,bookId,chapterId)
+ setErrorType('')
+ setDetails('')
+ setIsOpen(false)
+ }
+ const handleExit = (event: React.MouseEvent) => {
+ setErrorType('')
+ setDetails('')
+ if (modalRef.current && !modalRef.current.contains(event.target as Node)) {
+ setIsOpen(false)
+ }
+ event.stopPropagation()
+ }
+ return (
+
+
+ {isOpen && (
+
e.stopPropagation()}>
+
+
Report Chapter
+
+
+
+
+ )}
+
+ );
+}
+
+export default ReportButton;
\ No newline at end of file
diff --git a/src/lib/api.tsx b/src/lib/api.tsx
index 9cae2a2..fccc12f 100644
--- a/src/lib/api.tsx
+++ b/src/lib/api.tsx
@@ -1,9 +1,36 @@
import { addDays, subDays } from "date-fns";
-import { Book, Chapter, Editor, Announcement, Glossary } from "./types";
+import { Book, Chapter, Editor, Announcement, Glossary, Report } from "./types";
const API_URL = process.env.NEXT_PUBLIC_API_URL as string;
const API_TOKEN = process.env.STRAPI_API_TOKEN as string;
+export async function createFromAPI(
+ endpoint: string,
+ payload: string,
+ options: RequestInit = {},
+): Promise {
+
+ const headers: HeadersInit = {
+ Authorization: `Bearer ${API_TOKEN}`,
+ "Content-Type": "application/json",
+ };
+
+
+ const config: RequestInit = {
+ method: "POST",
+ headers,
+ body: payload,
+ ...options,
+ }
+
+
+ const response = await fetch(`${API_URL}${endpoint}`, config)
+ if(!response.ok) {
+ throw new Error(`API request failed with status ${response.status}`)
+ }
+ return response.json()
+}
+
export async function fetchFromAPI(
endpoint: string,
options: RequestInit = {}
@@ -13,8 +40,9 @@ export async function fetchFromAPI(
"Content-Type": "application/json",
};
+
const config: RequestInit = {
- method: "GET", // Default method is GET
+ method: "GET",
headers,
...options,
};
@@ -133,4 +161,21 @@ export async function fetchAnnouncementById(announcementId: string): Promise {
const data = await fetchFromAPI(`/api/glossaries?filters[book][documentId]=${bookId}`);
return data[0];
+}
+export async function createReport(
+ error_type: string,
+ details: string,
+ book_id: string,
+ chapter_id: string
+): Promise {
+ const payload = {
+ data: {
+ error_type,
+ details,
+ book: book_id,
+ chapter: chapter_id
+ }
+ }
+ const data = await createFromAPI(`/api/reports`, JSON.stringify(payload))
+ return data
}
\ No newline at end of file