From c8bb06384757e5c1351265103d6b6ad724342131 Mon Sep 17 00:00:00 2001
From: alceil <47685349+alceil@users.noreply.github.com>
Date: Sat, 16 May 2026 18:58:58 +0530
Subject: [PATCH] Refactor paste components into modular utilities
---
src/components/App/App.jsx | 82 +++++------------
src/components/HomePage/HomePage.jsx | 18 ++++
src/components/Modal/Modal.jsx | 68 ++++----------
src/components/ShareActions/ShareActions.jsx | 18 ++++
src/components/ShareContent/ShareContent.jsx | 10 ++
src/components/SharePage/SharePage.jsx | 96 ++++++--------------
src/components/Typing/Typing.jsx | 41 +++++----
src/config/editorConfig.js | 11 +++
src/config/toastConfig.js | 16 ++++
src/services/pasteService.js | 13 +++
src/utils/sanitizePasteContent.js | 23 +++++
src/utils/shareUrl.js | 1 +
12 files changed, 199 insertions(+), 198 deletions(-)
create mode 100644 src/components/HomePage/HomePage.jsx
create mode 100644 src/components/ShareActions/ShareActions.jsx
create mode 100644 src/components/ShareContent/ShareContent.jsx
create mode 100644 src/config/editorConfig.js
create mode 100644 src/config/toastConfig.js
create mode 100644 src/services/pasteService.js
create mode 100644 src/utils/sanitizePasteContent.js
create mode 100644 src/utils/shareUrl.js
diff --git a/src/components/App/App.jsx b/src/components/App/App.jsx
index 2b29851..f136fbf 100644
--- a/src/components/App/App.jsx
+++ b/src/components/App/App.jsx
@@ -1,84 +1,52 @@
-import React, { useState } from "react";
-import Header from "../Header/Header";
-
-import Typing from "../Typing/Typing";
-import axios from "axios";
+import React, { useCallback, useState } from "react";
import { Route, Switch, useHistory, withRouter } from "react-router-dom";
+import { toast } from "react-toastify";
+import useDarkMode from "use-dark-mode";
+import Header from "../Header/Header";
+import HomePage from "../HomePage/HomePage";
import SharePage from "../SharePage/SharePage";
-import style from "./App.module.css";
import ToggleDarkMode from "../ToggleDarkMode/ToggleDarkMode";
-import { ToastContainer, toast } from 'react-toastify';
-
-// Dark mode custom
-import useDarkMode from 'use-dark-mode';
+import { createPaste } from "../../services/pasteService";
+import { hasPasteContent } from "../../utils/sanitizePasteContent";
+import style from "./App.module.css";
const App = () => {
const history = useHistory();
const [shareText, setShareText] = useState("");
- const [created, setCreated] = useState(false);
-
const darkMode = useDarkMode(false);
- // const [routeNav, setRouteNav] = useState(false);
-
- const handleInputChange = (inputValue) => {
+ const handleInputChange = useCallback((inputValue) => {
setShareText(inputValue);
- };
+ }, []);
- const onSubmit = (inputValue) => {
- setCreated(true);
- console.log("pressed dude");
- // console.log(shareText);
- //http://localhost:4000
- console.log("Text:"+shareText);
- if(shareText === "
" || !shareText ) {
- console.log("Empty Text");
+ const onSubmit = async () => {
+ if (!hasPasteContent(shareText)) {
toast.error("Error : Empty Text");
-
- } else {
- axios
- .post("https://justpasteitapi.herokuapp.com/add", { content: shareText })
- .then((response) => {
- let id = response.data["_id"];
- history.push("/" + id);
+ return;
+ }
- console.log(id);
- })
- .catch((error) => {
- console.log(error);
- });
+ try {
+ const paste = await createPaste(shareText);
+ history.push(`/${paste._id}`);
+ } catch (error) {
+ toast.error("Error : Unable to save text");
+ console.error(error);
}
- }
+ };
return (
);
};
diff --git a/src/components/HomePage/HomePage.jsx b/src/components/HomePage/HomePage.jsx
new file mode 100644
index 0000000..2b45252
--- /dev/null
+++ b/src/components/HomePage/HomePage.jsx
@@ -0,0 +1,18 @@
+import React from "react";
+import { ToastContainer } from "react-toastify";
+import Typing from "../Typing/Typing";
+import { defaultToastConfig } from "../../config/toastConfig";
+
+const HomePage = ({ handleInputChange, onSubmit }) => (
+ <>
+
+
+ >
+);
+
+export default HomePage;
diff --git a/src/components/Modal/Modal.jsx b/src/components/Modal/Modal.jsx
index e2e90f0..948e02d 100644
--- a/src/components/Modal/Modal.jsx
+++ b/src/components/Modal/Modal.jsx
@@ -3,11 +3,12 @@ import "./Modal.css";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import { CopyToClipboard } from "react-copy-to-clipboard";
-import Button from '../Button/Button';
+import Button from "../Button/Button";
+import { defaultToastConfig, toastStyle } from "../../config/toastConfig";
+import { getShareUrl } from "../../utils/shareUrl";
+
const MODAL_STYLES = {
position: "fixed",
- // display: 'flex',
- // flexFlow: 'column',
width: "50%",
top: "50%",
left: "50%",
@@ -28,31 +29,18 @@ const OVERLAY_STYLES = {
zIndex: 1000,
};
-const getUrl = (id) => {
- return `${window.location.protocol}//${window.location.host}/${id}`;
-
-}
-
-export default function Modal({ id, open, children, onClose }) {
+const Modal = ({ id, open, onClose }) => {
if (!open) return null;
- console.log(id);
- var url = getUrl(id);
+
+ const url = getShareUrl(id);
const notify = () => toast("Link Copied📋");
+
return (
<>
@@ -64,39 +52,15 @@ export default function Modal({ id, open, children, onClose }) {
-
+
-
+
-
- {/*
-
- */}
>
);
- // document.getElementById('portal')
-}
+};
+
+export default Modal;
diff --git a/src/components/ShareActions/ShareActions.jsx b/src/components/ShareActions/ShareActions.jsx
new file mode 100644
index 0000000..6faecad
--- /dev/null
+++ b/src/components/ShareActions/ShareActions.jsx
@@ -0,0 +1,18 @@
+import React from "react";
+import { ToastContainer } from "react-toastify";
+import Button from "../Button/Button";
+import style from "../SharePage/SharePage.module.css";
+import { defaultToastConfig, toastStyle } from "../../config/toastConfig";
+
+const ShareActions = ({ onCopy, onShare }) => (
+
+
+
+
+
+);
+
+export default ShareActions;
diff --git a/src/components/ShareContent/ShareContent.jsx b/src/components/ShareContent/ShareContent.jsx
new file mode 100644
index 0000000..7fe4db7
--- /dev/null
+++ b/src/components/ShareContent/ShareContent.jsx
@@ -0,0 +1,10 @@
+import React from "react";
+import style from "../SharePage/SharePage.module.css";
+
+const ShareContent = ({ content }) => (
+
+);
+
+export default ShareContent;
diff --git a/src/components/SharePage/SharePage.jsx b/src/components/SharePage/SharePage.jsx
index 3770edc..7f26523 100644
--- a/src/components/SharePage/SharePage.jsx
+++ b/src/components/SharePage/SharePage.jsx
@@ -1,87 +1,45 @@
-import React, { useState,useEffect}from "react";
-import {useParams} from 'react-router-dom';
-import Button from "../Button/Button";
-import Modal from '../Modal/Modal'
-import axios from "axios";
+import React, { useCallback, useEffect, useState } from "react";
+import { useParams } from "react-router-dom";
import copy from "copy-to-clipboard";
-import style from "./SharePage.module.css";
-import { ToastContainer, toast } from 'react-toastify';
-import xss from 'xss';
-import 'react-toastify/dist/ReactToastify.css';
-import 'highlight.js/styles/atom-one-light.css';
+import { toast } from "react-toastify";
+import "react-toastify/dist/ReactToastify.css";
+import "highlight.js/styles/atom-one-light.css";
+import Modal from "../Modal/Modal";
+import ShareActions from "../ShareActions/ShareActions";
+import ShareContent from "../ShareContent/ShareContent";
+import { getPaste } from "../../services/pasteService";
+import { sanitizePasteContent } from "../../utils/sanitizePasteContent";
const SharePage = () => {
- const {id} = useParams();
- const [isOpen, setIsOpen] = useState(false)
- const [data, setData] = useState('');
-
- const options = {
- whiteList: {
- pre: ["class"],
- span: ["class"],
- p: [],
- br: [],
- strong: [],
- em: [],
- u: [],
- ul: [],
- li: [],
- ol: [],
- a: ["href", "rel", "target"]
- }
- };
+ const { id } = useParams();
+ const [isOpen, setIsOpen] = useState(false);
+ const [data, setData] = useState("");
useEffect(() => {
const fetchData = async () => {
- const result = await axios(
- `https://justpasteitapi.herokuapp.com/add/${id}`
- );
-
- let text = xss(result.data['content'], options);
- setData(text);
- console.log(result.data['content']); // Debug log
+ try {
+ const paste = await getPaste(id);
+ setData(sanitizePasteContent(paste.content));
+ } catch (error) {
+ toast.error("Error : Unable to load text");
+ console.error(error);
+ }
};
-
+
fetchData();
- }, [data, id]);
+ }, [id]);
-
- const notify = () =>{
+ const notify = useCallback(() => {
copy(data);
toast("Text Copied Successfully 📋");
- }
-
+ }, [data]);
return (
-
-
{/*Data was sanitized with the XSS library*/}
-
-
-
-
-
setIsOpen(false)}/>
+
+ setIsOpen(true)} />
+ setIsOpen(false)} />
-
);
};
diff --git a/src/components/Typing/Typing.jsx b/src/components/Typing/Typing.jsx
index c0d0797..5e1662e 100644
--- a/src/components/Typing/Typing.jsx
+++ b/src/components/Typing/Typing.jsx
@@ -1,40 +1,41 @@
-import React, {useState, useEffect} from "react";
+import React, { useEffect, useState } from "react";
import style from "./Typing.module.css";
-import hljs from 'highlight.js';
-import ReactQuill from 'react-quill';
+import hljs from "highlight.js";
+import ReactQuill from "react-quill";
import Button from "../Button/Button";
-import 'react-quill/dist/quill.snow.css';
-import 'highlight.js/styles/atom-one-light.css';
+import { editorModules } from "../../config/editorConfig";
+import "react-quill/dist/quill.snow.css";
+import "highlight.js/styles/atom-one-light.css";
const Typing = ({ handleInputChange, onSubmit }) => {
- const [value, setValue] = useState();
+ const [value, setValue] = useState("");
- useEffect(() => {
- hljs.configure({useBR: false});
+ useEffect(() => {
+ hljs.configure({ useBR: false });
}, []);
- useEffect(() => { // Called on value change
+ useEffect(() => {
handleInputChange(value);
- console.log("input debug: " + value);
}, [handleInputChange, value]);
- return (
-
);
};
diff --git a/src/config/editorConfig.js b/src/config/editorConfig.js
new file mode 100644
index 0000000..78d235d
--- /dev/null
+++ b/src/config/editorConfig.js
@@ -0,0 +1,11 @@
+export const editorModules = {
+ syntax: {
+ setInterval: 10,
+ },
+ toolbar: [
+ ["bold", "italic", "underline", "blockquote"],
+ [{ list: "ordered" }, { list: "bullet" }],
+ ["link"],
+ ["code-block"],
+ ],
+};
diff --git a/src/config/toastConfig.js b/src/config/toastConfig.js
new file mode 100644
index 0000000..ab73a8f
--- /dev/null
+++ b/src/config/toastConfig.js
@@ -0,0 +1,16 @@
+export const defaultToastConfig = {
+ position: "bottom-center",
+ autoClose: 1000,
+ hideProgressBar: true,
+ newestOnTop: false,
+ closeOnClick: true,
+ rtl: false,
+ pauseOnFocusLoss: true,
+ draggable: true,
+ pauseOnHover: true,
+};
+
+export const toastStyle = (paddingLeft) => ({
+ color: "black",
+ paddingLeft,
+});
diff --git a/src/services/pasteService.js b/src/services/pasteService.js
new file mode 100644
index 0000000..ead40f9
--- /dev/null
+++ b/src/services/pasteService.js
@@ -0,0 +1,13 @@
+import axios from "axios";
+
+const API_BASE_URL = "https://justpasteitapi.herokuapp.com";
+
+export const createPaste = async (content) => {
+ const response = await axios.post(`${API_BASE_URL}/add`, { content });
+ return response.data;
+};
+
+export const getPaste = async (id) => {
+ const response = await axios(`${API_BASE_URL}/add/${id}`);
+ return response.data;
+};
diff --git a/src/utils/sanitizePasteContent.js b/src/utils/sanitizePasteContent.js
new file mode 100644
index 0000000..abc87b0
--- /dev/null
+++ b/src/utils/sanitizePasteContent.js
@@ -0,0 +1,23 @@
+import xss from "xss";
+
+export const EMPTY_EDITOR_CONTENT = "
";
+
+const sanitizerOptions = {
+ whiteList: {
+ pre: ["class"],
+ span: ["class"],
+ p: [],
+ br: [],
+ strong: [],
+ em: [],
+ u: [],
+ ul: [],
+ li: [],
+ ol: [],
+ a: ["href", "rel", "target"],
+ },
+};
+
+export const hasPasteContent = (content) => Boolean(content && content !== EMPTY_EDITOR_CONTENT);
+
+export const sanitizePasteContent = (content) => xss(content || "", sanitizerOptions);
diff --git a/src/utils/shareUrl.js b/src/utils/shareUrl.js
new file mode 100644
index 0000000..80701cd
--- /dev/null
+++ b/src/utils/shareUrl.js
@@ -0,0 +1 @@
+export const getShareUrl = (id) => `${window.location.protocol}//${window.location.host}/${id}`;