Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Newsletter #41

Merged
merged 3 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
958 changes: 867 additions & 91 deletions my-app/package-lock.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion my-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,19 @@
},
"dependencies": {
"@headlessui/react": "^2.1.8",
"@wojtekmaj/react-hooks": "^1.21.0",
"framer-motion": "^11.5.6",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-helmet": "^6.1.0",
"react-icons": "^5.3.0",
"react-pdf": "^9.1.1",
"react-router-dom": "^6.26.2",
"react-secure-storage": "^1.3.2",
"react-slick": "^0.30.2",
"slick-carousel": "^1.8.1",
"toastify-js": "^1.12.0"
"toastify-js": "^1.12.0",
"vite-plugin-static-copy": "^1.0.6"
},
"devDependencies": {
"@eslint/js": "^9.9.0",
Expand Down
Binary file added my-app/public/Newsletter.pdf
Binary file not shown.
2 changes: 2 additions & 0 deletions my-app/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Events from "./pages/Events";
import Base from "./layouts/Base";
import Subscribe from "./components/Subscribe";
import { useState } from "react";
import NewsletterPage from "./pages/NewsletterPage";

export default function App() {
const [isVisible, setIsVisible] = useState(false);
Expand All @@ -27,6 +28,7 @@ export default function App() {
<Route path="/community" element={<Community />} />
<Route path="/events" element={<Events />} />
<Route path="/contact-us" element={<ContactForm />} />
<Route path="/newsletter" element={<NewsletterPage />} />
<Route path="*" element={<NotFound />} />
</Routes>
</Base>
Expand Down
2 changes: 1 addition & 1 deletion my-app/src/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const navigation = [
{ name: "Home", to: "/" },
{ name: "Community", to: "/community" },
{ name: "Events", to: "/events" },
{ name: "Newsletter", to: "/newsletter" },
{ name: "About us", to: "about-us" },
{ name: "Contact us", to: "/contact-us" },
];
export { navigation };
4 changes: 2 additions & 2 deletions my-app/src/pages/Community.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,8 @@ export default function Community() {
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-blue-700",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-blue-400 focus:outline-none",
selected
? "bg-white shadow"
: "text-blue-100 hover:bg-white/[0.12] hover:text-white"
? "bg-white shadow "
: "text-white hover:bg-white/[0.12] hover:text-blue-100"
)
}
>
Expand Down
2 changes: 1 addition & 1 deletion my-app/src/pages/Events.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ export default function Events() {
"ring-white ring-opacity-60 ring-offset-2 ring-offset-blue-400 focus:outline-none",
selected
? "bg-white shadow"
: "text-blue-100 hover:bg-white/[0.12] hover:text-white"
: " text-white hover:bg-white/[0.12] hover:text-blue-100"
)
}
>
Expand Down
180 changes: 180 additions & 0 deletions my-app/src/pages/NewsletterPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import { pdfjs } from "react-pdf";
import { useCallback, useEffect, useMemo, useState } from "react";
import { Document, Page } from "react-pdf";
import { useResizeObserver } from "@wojtekmaj/react-hooks";
import "react-pdf/dist/esm/Page/AnnotationLayer.css";
import "react-pdf/dist/esm/Page/TextLayer.css";
import { IoChevronBack, IoChevronForward } from "react-icons/io5";
import { API_URL } from "../lib/constants";

import "../styles/newsletter.css";
import Newsletter from "../components/Newsletter";

pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
const maxWidth = 800;
const resizeObserverOptions = {};

const NewsletterPage = () => {
const [file, setFile] = useState();
const [editions, setEditions] = useState([]);
const [numPages, setNumPages] = useState();
const [pageNumber, setPageNumber] = useState(1);
const [containerRef, setContainerRef] = useState(null);
const [containerWidth, setContainerWidth] = useState();
const [loading, setLoading] = useState(true);

// Memoize the options object to prevent unnecessary reloads
const options = useMemo(
() => ({
cMapUrl: `https://unpkg.com/pdfjs-dist@${pdfjs.version}/cmaps/`,
}),
[]
);

const onDocumentLoadSuccess = ({ numPages }) => {
setNumPages(numPages);
};

const onResize = useCallback((entries) => {
const [entry] = entries;
if (entry) {
setContainerWidth(entry.contentRect.width);
}
}, []);

useResizeObserver(containerRef, resizeObserverOptions, onResize);

const getNewsletters = async () => {
try {
const response = await fetch(`${API_URL}/newsletter`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});

const data = await response.json();
if(data.success){
setEditions(data.newsletter);
if(data.newsletter.length>0) getNewsletter(data.newsletter[0].id)
}
setLoading(false);
} catch (error) {
setLoading(false);
}
};

const getNewsletter = async (id) => {
try {
const response = await fetch(`${API_URL}/newsletter/${id}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});

const data = await response.json();
if(data.success){
const pdfResponse = await fetch(data.newsletter.link);
const blob = await pdfResponse.blob();
const fileUrl = URL.createObjectURL(blob);
setFile(fileUrl);
}
setLoading(false);
} catch (error) {
setLoading(false);
}
};

useEffect(()=>{
getNewsletters();
},[])

const forward = () => {
if (pageNumber + 1 <= numPages) setPageNumber(pageNumber + 1);
};

const backward = () => {
if (pageNumber - 1 >= 1) setPageNumber(pageNumber - 1);
};

const [selectedValue, setSelectedValue] = useState('Option 1');

// Handle change event
const handleChange = (event) => {
setLoading(true);
setSelectedValue(event.target.value);
getNewsletter(event.target.value);
};

return (
<div className="text-white flex flex-col justify-center">
<h1 className="text-4xl tracking-tight my-2 font-extrabold text-pastel text-center sm:text-5xl md:text-6xl">
Newsletters
</h1>
<div className="flex justify-center mt-4 mb-8">
<div className="mx-auto">
<label htmlFor="dropdown" className="mb-2 text-lg font-medium text-gray-300 text-center">
Select an edition:
</label>
<select
id="dropdown"
value={selectedValue}
onChange={handleChange}
className="block w-64 px-3 py-2 border border-gray-300 bg-gray-700 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
>
{
editions.map((item, index)=>{
return <option key={index} value={item.id}>{item.edition}</option>
})
}
</select>
</div>
</div>
{
loading&&
<div className="h-24 w-4/6 rounded-xl bg-white/30 text-transparent mx-auto animate-pulse">
asda
</div>
}
{!loading&&file&&
<div>
<div className="flex justify-center">
<div className="flex justify-center gap-12">
<button onClick={backward}><IoChevronBack size={25} /></button>
{pageNumber} of {numPages}
<button onClick={forward}><IoChevronForward size={25} /></button>
</div>
</div>
<div>
<div className="Example__container__document mx-auto" ref={setContainerRef}>
<Document
file={file}
onLoadSuccess={onDocumentLoadSuccess}
options={options}
>
<Page
pageNumber={pageNumber}
width={
containerWidth ? Math.min(containerWidth, maxWidth) : maxWidth
}
/>
</Document>
</div>
</div>
<div className="flex justify-center">
<div className="flex justify-center gap-12">
<button onClick={backward}><IoChevronBack size={25} /></button>
{pageNumber} of {numPages}
<button onClick={forward}><IoChevronForward size={25} /></button>
</div>
</div>
</div>}
<div className="my-6">
<Newsletter />
</div>
</div>
);
};

export default NewsletterPage;
51 changes: 51 additions & 0 deletions my-app/src/styles/newsletter.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
.Example input,
.Example button {
font: inherit;
}

.Example header {
background-color: #323639;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.5);
padding: 20px;
color: white;
}

.Example header h1 {
font-size: inherit;
margin: 0;
}

.Example__container {
display: flex;
flex-direction: column;
align-items: center;
margin: 10px 0;
padding: 10px;
}

.Example__container__load {
margin-top: 1em;
color: white;
}

.Example__container__document {
width: 100%;
max-width: calc(100% - 2em);
margin: 1em 0;
}

.Example__container__document .react-pdf__Document {
display: flex;
flex-direction: column;
align-items: center;
}

.Example__container__document .react-pdf__Page {
margin: 1em 0;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.5);
}

.Example__container__document .react-pdf__message {
padding: 20px;
color: white;
}
54 changes: 0 additions & 54 deletions package-lock.json

This file was deleted.

5 changes: 0 additions & 5 deletions package.json

This file was deleted.