Skip to content

Commit

Permalink
Toggle button, Navbar and minor fix
Browse files Browse the repository at this point in the history
  • Loading branch information
dhruvjindal555 committed Jul 27, 2024
1 parent 819303f commit 0662bf1
Show file tree
Hide file tree
Showing 12 changed files with 102 additions and 106 deletions.
3 changes: 2 additions & 1 deletion frontend/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<link rel="icon" href="newspaper-solid.svg" type="image/x-icon"/>
<title>NewsStore</title>
</head>
<body class="light" >
<noscript>You need to enable JavaScript to run this app.</noscript>
Expand Down
1 change: 1 addition & 0 deletions frontend/public/newspaper-solid.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion frontend/src/Components/FavouriteItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import toast, { Toaster } from 'react-hot-toast';
function FavouriteItem({ article, getFavourite }) {
// Function to remove an article from favorites
const removeFromFavourites = async () => {
const url = `http://localhost:8888/favourites/remove/${article._id}`;
const url = `https://cantilever-task-2.onrender.com/favourites/remove/${article._id}`;
const response = await fetch(url, {
method: 'DELETE',
headers: {
Expand Down
60 changes: 36 additions & 24 deletions frontend/src/Components/Favourites.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,41 @@
import React, { useState, useEffect } from 'react';
import FavouriteItem from './FavouriteItem';
import toast, { Toaster } from 'react-hot-toast';
import Pagination from './Pagination';
import Spinner from './Spinner';

function Favourites() {
const [articles, setArticles] = useState([]);

const [loading, setLoading] = useState(true)
// Function to fetch favourite articles from the server
const getFavourite = async () => {
if (!localStorage.getItem('authToken')) {
console.log("Please login to view your favourites");
return;
}
const url = `http://localhost:8888/favourites`;
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
"authToken": localStorage.getItem('authToken')
try {
if (!localStorage.getItem('authToken')) {
console.log("Please login to view your favourites");
return;
}
const url = `https://cantilever-task-2.onrender.com/favourites`;
setLoading(true)
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
"authToken": localStorage.getItem('authToken')
}
});
const data = await response.json();
setLoading(false)
if (data.success) {
setArticles(data.articles); // Update state with fetched articles
console.log("Favourite articles fetched successfully")
console.log(data.articles);
} else {
console.log(data.message);
}
});
const data = await response.json();
if (data.success) {
setArticles(data.articles); // Update state with fetched articles
// toast("Articles fetched successfully")
console.log(data.articles);
} else {
console.log(data.message);
} catch (error) {
console.error("An error occurred while fetching the favourites: " + error.message);
setLoading(false)
setArticles([])
console.log("Favourites fetched failed")
console.log(error);
}
};

Expand All @@ -41,14 +50,17 @@ function Favourites() {
<h1 className='text-5xl font-semibold'>Favourites</h1>
</div>
<div>
<div className='sm:grid sm:gap-3 xl:grid-cols-4 lg:grid-cols-3 grid-cols-2 gap-y-5 flex flex-col gap-1'>
<div className='sm:grid sm:gap-3 xl:grid-cols-4 lg:grid-cols-3 grid-cols-2 gap-y-5 flex flex-col gap-1 pb-10'>
{articles.length > 0 ? articles.map((article) => {
return (
<FavouriteItem key={article.url} article={article} getFavourite={getFavourite} />
);
}) : "ARTICLES NOT AVAILABLE"}
}) : (loading ?
<div className='w-full mx-auto xl:col-span-4 lg:col-span-3 col-span-2 '>
<Spinner />
</div>
: "ARTICLES NOT AVAILABLE")}
</div>
<Pagination totalResults={articles.length} />
</div>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/Components/LatestNews.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState, useEffect, useContext } from 'react';
import News from './News';
import Spinner from './Spinner';
import toast, { Toaster } from 'react-hot-toast';
import toast from 'react-hot-toast';
import Pagination from './Pagination';
import NewsContext from '../contexts/favourites/NewsContext';

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/Components/LogIn.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function LogIn() {
const handleSubmit = async (e) => {
e.preventDefault();
// Send POST request to login endpoint
const response = await fetch("http://localhost:8888/auth/login", {
const response = await fetch("https://cantilever-task-2.onrender.com/auth/login", {
method: "POST",
headers: {
"Content-Type": "application/json"
Expand Down
21 changes: 11 additions & 10 deletions frontend/src/Components/Navbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import toast, { Toaster } from 'react-hot-toast';
import NewsContext from '../contexts/favourites/NewsContext';
import { Link, useNavigate } from "react-router-dom";
import ToggleButton from './ToggleButton';
import gsap from 'gsap';
import { useGSAP } from '@gsap/react';
gsap.registerPlugin(useGSAP);


// Utility function to join class names conditionally
function classNames(...classes) {
return classes.filter(Boolean).join(' ')
}

export default function Navbar() {

const navRef = useRef(null)
const { search, setSearch, fetchQuery } = useContext(NewsContext); // Extracting context values
const Navigate = useNavigate(); // Hook for navigation
Expand All @@ -30,9 +30,9 @@ export default function Navbar() {
toast('Logged out successfully');
Navigate('/');
} else {
Navigate('LogIn');
handleClickItem('Home');
return Navigate('LogIn');
}
handleClickItem('Home');
}

// Function to handle search query
Expand All @@ -46,7 +46,7 @@ export default function Navbar() {
// Function to handle navigation item click
const handleClickItem = (current) => {
if (current === 'Favourites' && !window.localStorage.getItem('authToken')) {
window.location.href = '/';

toast("Please login to access your favorites");
}
setNavigation(navigation.map((item) => {
Expand All @@ -64,9 +64,10 @@ export default function Navbar() {
}));
}


return (
<div ref={navRef} className='sticky top-0 mx-2 sm:mx-8 md:mx-12 lg:mx-16 xl:mx-20 z-10'>
<div ref={navRef}
className='sticky top-0 px-1 sm:px-8 md:px-12 lg:px-16 xl:px-20 z-10 bg-my-gradient-1 dark:bg-my-gradient-2'>
<Toaster position="top-center" reverseOrder={false} gutter={8} /> {/* Toast notifications */}
<Disclosure as="nav" className="">
{({ open }) => (
Expand All @@ -86,7 +87,7 @@ export default function Navbar() {
</DisclosureButton>
</div>
<div className="flex flex-1 items-center justify-center sm:items-stretch sm:justify-start">
<a href='/' className="flex flex-shrink-0 dark:text-white items-center">
<a href='/' className="flex ml-2 flex-shrink-0 dark:text-white items-center">
<span className='text-3xl font-semibold'>NewsStore</span>
</a>
<div className="hidden sm:ml-6 sm:block">
Expand Down Expand Up @@ -126,7 +127,7 @@ export default function Navbar() {
{navigation.map((item) => (
<Link
key={item.name}
to={item.to}
// to={item.to}
onClick={(e) => {
handleClickItem(e.target.textContent);
}}
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/Components/NewsItem.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import toast, { Toaster } from 'react-hot-toast';
import toast from 'react-hot-toast';

function NewsItem({ article }) {
const addToFavourites = async () => {
Expand All @@ -9,7 +9,7 @@ function NewsItem({ article }) {
}

// Define the URL for adding favourites
const url = `http://localhost:8888/favourites/add`
const url = `https://cantilever-task-2.onrender.com/favourites/add`

// Send POST request to add the article to favourites
const response = await fetch(url, {
Expand Down Expand Up @@ -72,7 +72,7 @@ function NewsItem({ article }) {
<p>Source: {article.source.name}</p>
<p>Author: {article.author}</p>
</div>
<a href={article.url} target='_blank' className="flex justify-between items-center px-3 py-2 text-sm font-medium text-center text-white bg-blue-600 rounded-lg hover:bg-blue-700 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-600 dark:focus:ring-blue-700">
<a href={article.url} rel="noreferrer" target='_blank' className="flex justify-between items-center px-3 py-2 text-sm font-medium text-center text-white bg-blue-600 rounded-lg hover:bg-blue-700 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-600 dark:focus:ring-blue-700">
Read more
<svg className="rtl:rotate-180 w-3.5 h-3.5 ms-2" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 10">
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M1 5h12m0 0L9 1m4 4L9 9" />
Expand Down
86 changes: 33 additions & 53 deletions frontend/src/Components/Pagination.js
Original file line number Diff line number Diff line change
@@ -1,93 +1,73 @@
import React, { useContext, useState, useEffect } from 'react';
import React, { useContext } from 'react';
import NewsContext from '../contexts/favourites/NewsContext';

function Pagination({ totalResults }) {
const { page, setPage, search, fetchArticles, fetchQuery } = useContext(NewsContext); // Extracting context values
const [pageStart, setPageStart] = useState(1); // State for starting page number
const [pageEnd, setPageEnd] = useState(20); // State for ending page number

const totalPages = Math.ceil(totalResults / 20)
// Function to handle previous button click
const handlePrevious = () => {
// console.log(page-1);
setPage(page - 1);
if (search === "") {
fetchArticles();
} else {
fetchQuery();
}
setPageStart(pageStart - 20);
setPageEnd(pageEnd - 20);
console.log(pageStart, pageEnd);
};

// Function to handle next button click
const handleNext = () => {
// console.log(totalPages);
// console.log(page+1);
setPage(page + 1);
setPageStart(20 * (page - 1));
setPageEnd(20 * page);
if (search === "") {
fetchArticles();
} else {
console.log("Search", search);
fetchQuery();
}
console.log("pageStart", pageStart, "pageEnd", pageEnd);
};

return (
<div className="flex items-center justify-between bg-transparent px-4 py-3 sm:px-6">
<div className="flex flex-1 justify-between sm:hidden">
<button
disabled={pageStart === 1}
onClick={handlePrevious}
<div className="sm:flex sm:flex-1 sm:justify-between hidden ">
<button
disabled={page === 1}
onClick={handlePrevious}
className="relative inline-flex items-center rounded-md border bg-transparent px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50"
>
Previous
</button>
<button
disabled={pageEnd === totalResults}
onClick={handleNext}
<button
disabled={page === totalPages}
onClick={handleNext}
className="relative ml-3 inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50"
>
Next
</button>
</div>
<div className="hidden sm:flex sm:flex-1 sm:items-center sm:justify-between">
<div>
<p className="text-sm text-gray-700 dark:text-gray-100">
Showing
<span className="font-medium px-1">{totalResults === 0 ? "0" : pageStart}</span>
to
<span className="font-medium px-1">{totalResults === 0 ? "0" : pageEnd}</span>
of
<span className="font-medium px-1">{totalResults}</span>
results
</p>
</div>
<div>
<nav className="isolate inline-flex -space-x-px rounded-md shadow-sm" aria-label="Pagination">
<button
disabled={pageStart === 1}
onClick={handlePrevious}
className="border-black border-2 mx-2 relative inline-flex items-center rounded-l-md px-2 py-2 text-black dark:hover:text-black ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-20 focus:outline-offset-0"
>
<span className="sr-only">Previous</span>
<svg className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fillRule="evenodd" d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z" clipRule="evenodd" />
</svg>
</button>
<div className="sm:hidden flex flex-1 items-center justify-between">
<button
disabled={page === 1}
onClick={handlePrevious}
className="border-black border-2 mx-2 relative inline-flex items-center rounded-l-md px-2 py-2 text-black dark:hover:text-black ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-20 focus:outline-offset-0"
>
<span className="sr-only">Previous</span>
<svg className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fillRule="evenodd" d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z" clipRule="evenodd" />
</svg>
</button>

<button
disabled={pageEnd === totalResults}
onClick={handleNext}
className="border-black mx-2 border-2 relative inline-flex items-center rounded-r-md px-2 py-2 text-black dark:hover:text-black ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-20 focus:outline-offset-0"
>
<span className="sr-only">Next</span>
<svg className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fillRule="evenodd" d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z" clipRule="evenodd" />
</svg>
</button>
</nav>
</div>
<button
disabled={page === totalPages}
onClick={handleNext}
className="border-black mx-2 border-2 relative inline-flex items-center rounded-r-md px-2 py-2 text-black dark:hover:text-black ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-20 focus:outline-offset-0"
>
<span className="sr-only">Next</span>
<svg className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fillRule="evenodd" d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z" clipRule="evenodd" />
</svg>
</button>
</div>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/Components/SignUp.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function SignUp() {
// Check if password and confirm password match
if (credentials.password === credentials.confirmPassword) {
// Send POST request to signup endpoint
const response = await fetch("http://localhost:8888/auth/signup", {
const response = await fetch("https://cantilever-task-2.onrender.com/auth/signup", {
method: "POST",
headers: {
"Content-Type": "application/json"
Expand Down
17 changes: 9 additions & 8 deletions frontend/src/Components/ToggleButton.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import React from 'react'

function ToggleButton() {
// Function to toggle between light and dark themes


const toggleTheme = () => {
console.log("theme clicked"); // Log when the theme button is clicked
console.log("theme clicked");
if (document.body.classList.contains('light')) {
document.body.classList.remove('light'); // Remove 'light' class if present
document.body.classList.add('dark'); // Add 'dark' class
document.body.classList.remove('light');
document.body.classList.add('dark');
} else {
document.body.classList.remove('dark'); // Remove 'dark' class if present
document.body.classList.add('light'); // Add 'light' class
document.body.classList.remove('dark');
document.body.classList.add('light');
}
}
};

return (
<div>
<div className="mx-1 sm:mx-2 flex justify-center items-center ">
{/* Button to toggle the theme */}
<button onClick={toggleTheme}
className="sm:h-10 h-8 sm:w-10 w-8 rounded-lg p-1 bg-gray-100 dark:bg-gray-700">
className="sm:h-10 h-8 sm:w-10 w-8 rounded-lg p-1 ">
{/* Sun icon (light theme) */}
<svg className="fill-violet-700 block dark:hidden" fill="currentColor" viewBox="0 0 20 20">
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"></path>
Expand Down
Loading

0 comments on commit 0662bf1

Please sign in to comment.