diff --git a/reader/src/App.jsx b/reader/src/App.jsx
index c873adf..abd0978 100644
--- a/reader/src/App.jsx
+++ b/reader/src/App.jsx
@@ -28,104 +28,10 @@ import {
VRuleIcon,
} from "./icons/Icons";
import ResourcePage from "./ResourcePage.jsx";
-import NamePage from "./NamePage.jsx";
-import io from "socket.io-client";
-
-//const socket = io("http://localhost:3000");
+import { ViewPage, EditViewPage } from "./ViewPage.jsx";
const DIVIDER_AT = 16;
-//function SocketTest() {
-// const [booleanArray, setBooleanArray] = useState(new Array(10).fill(false));
-// const [isConnected, setIsConnected] = useState(false);
-//
-// useEffect(() => {
-// // Connection status
-// socket.on("connect", () => {
-// setIsConnected(true);
-// console.log("Connected to server");
-// });
-//
-// socket.on("disconnect", () => {
-// setIsConnected(false);
-// console.log("Disconnected from server");
-// });
-//
-// // Listen for array updates
-// socket.on("arrayChanged", (newArray) => {
-// setBooleanArray(newArray);
-// });
-//
-// // Cleanup on unmount
-// return () => {
-// socket.off("connect");
-// socket.off("disconnect");
-// socket.off("arrayChanged");
-// };
-// }, []);
-//
-// const toggleValue = (index) => {
-// const newValue = !booleanArray[index];
-//
-// // Emit update to server
-// socket.emit("setArrayValue", { index, value: newValue });
-// };
-//
-// const refreshArray = () => {
-// socket.emit("getArray");
-// };
-//
-// return (
-//
-//
Socket.IO Boolean Array
-//
-//
-// Status:{" "}
-//
-// {isConnected ? "Connected" : "Disconnected"}
-//
-//
-//
-//
-//
-//
-// {booleanArray.map((value, index) => (
-//
-// ))}
-//
-//
-//
-//
Current Array:
-//
{JSON.stringify(booleanArray)}
-//
-//
-// );
-//}
-
-const contextClass = {
- success: "bg-blue-600",
- error: "bg-red-600",
- info: "bg-gray-600",
- warning: "bg-orange-400",
- default: "bg-indigo-600",
- dark: "bg-white-600 font-gray-300",
-};
-
export function App() {
return (
<>
@@ -143,7 +49,8 @@ export function App() {
} />
} />
- } />
+ } />
+ } />
diff --git a/reader/src/ViewPage.jsx b/reader/src/ViewPage.jsx
new file mode 100644
index 0000000..b085251
--- /dev/null
+++ b/reader/src/ViewPage.jsx
@@ -0,0 +1,323 @@
+import { useState, useEffect, useMemo, useRef } from "react";
+import io from "socket.io-client";
+import { useStore } from "./store.js";
+import { marked } from "marked";
+import { TextIncreaseIcon, TextDecreaseIcon, HeartIcon } from "./icons/Icons.jsx";
+
+const socket = io(import.meta.env.VITE_API_BASE_URL);
+
+export function ViewPage() {
+ const iframeRef = useRef(null);
+ const config = useStore((state) => state.config);
+ const changeConfig = useStore((state) => state.changeConfig);
+
+ const [isConnected, setIsConnected] = useState(false);
+ const [data, setData] = useState(null);
+ const [selectedOptionId, setSelectedOptionId] = useState(null);
+ const [selectedIdx, setSelectedIdx] = useState(0);
+
+ const options = useMemo(() => {
+ return data?.options.map((option) => {
+ let fileContent = option.text || "**No Data!**";
+ fileContent = marked.parse(fileContent);
+
+ fileContent = `
+
+
+
+
+
+
+
+
+ ${fileContent}
+
+
+ `;
+ return { ...option, text: fileContent };
+ });
+ }, [data?.options]);
+
+ useEffect(() => {
+ socket.on("connect", () => setIsConnected(true));
+ socket.on("disconnect", () => setIsConnected(false));
+ socket.on("dataChanged", (newData) => {
+ setData(newData);
+ setSelectedOptionId(null);
+ setSelectedIdx(0);
+ });
+
+ return () => {
+ socket.off("connect");
+ socket.off("disconnect");
+ };
+ }, []);
+
+ useEffect(() => {
+ if (iframeRef.current && iframeRef.current.contentDocument) {
+ iframeRef.current.contentDocument.body.style.zoom = `${config.contentZoomLevel}%`;
+ }
+ }, [config.contentZoomLevel]);
+
+ if (!data) {
+ return (
+
+
+ Status:{" "}
+
+ {isConnected ? "Connected" : "Disconnected"}
+
+
+
+ );
+ }
+
+ return (
+
+
+ {data.title}
+
+
+
+
+
+
+ {config.contentZoomLevel}%
+
+
+
+
+
+
+
+
+
+
+
+ {options.map((option, optionIdx) => (
+
+ ))}
+
+
+ );
+}
+function LEditViewPage() {
+ const [isConnected, setIsConnected] = useState(false);
+
+ const [options, setOptions] = useState([]);
+ const [selectedOptionId, setSelectedOptionId] = useState(null);
+
+ const topics = useStore((state) => state.topics);
+ const [selectedTopicIdx, setSelectedTopicIdx] = useState(0);
+ const selectedTopic = topics[selectedTopicIdx];
+
+ useEffect(() => {
+ socket.on("connect", () => setIsConnected(true));
+ socket.on("disconnect", () => setIsConnected(false));
+ socket.on("selectedOptionChanged", (id) => setSelectedOptionId(id));
+
+ return () => {
+ socket.off("connect");
+ socket.off("disconnect");
+ socket.off("selectedOptionChanged");
+ };
+ }, []);
+
+ function handleSend() {
+ const finalV = {
+ title: `${selectedTopic.seq}. ${selectedTopic.title}`,
+ options,
+ };
+ socket.emit("setData", finalV);
+ setSelectedOptionId(null);
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ {options.map((option) => (
+
+
+
+ setOptions((prev) =>
+ prev.map((opt) =>
+ opt.id === option.id ? { ...opt, title: event.target.value } : opt,
+ ),
+ )
+ }
+ />
+
+ {selectedOptionId === option.id && YES!}
+
+
+ ))}
+
+
+ );
+}
+
+export function EditViewPage() {
+ return (
+
+
+
+ );
+}
+
+function LoadingWrapper({ children }) {
+ const isLoading = useStore((state) => state.isLoading);
+
+ if (isLoading) {
+ return null;
+ }
+
+ return children;
+}
+
+function Layout() {
+ const config = useStore((state) => state.config);
+
+ return (
+
+ {config.displayTitle && (
+
+ {topic ? `${topic.seq}: ${topic.title}` : `Конспект за Държавен Изпит`}
+
+ )}
+
+
+ );
+}
diff --git a/reader/src/icons/Icons.jsx b/reader/src/icons/Icons.jsx
index 3230aa5..6b878df 100644
--- a/reader/src/icons/Icons.jsx
+++ b/reader/src/icons/Icons.jsx
@@ -14,6 +14,25 @@ export function MyLocationIcon({ className }) {
);
}
+export function HeartIcon({ className }) {
+ return (
+
+ );
+}
+
export function TitleIcon({ className }) {
return (