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

Implement Chanakya Niti Books List #349

Closed
wants to merge 2 commits into from
Closed
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
72 changes: 72 additions & 0 deletions src/css/ChanakyaNews.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/* Individual newsletter card */
.nItem {
background-color: rgba(223, 223, 176, 0.4);
border-radius: 8px;
padding: 10px;
margin: 10px;
text-align: center;
box-shadow: 0 4px 8px #383636;
transition: transform 0.2s;
display: flex;
flex-direction: column;
justify-content: space-between;
height: 250px;
box-sizing: border-box;
width: calc(100% - 20px);
}

.nItem:hover {
border: 0.5px solid rgb(254, 251, 251);
transform: scale(1.05);
}

.card-des {
font-size: 1rem;
color: #383636;
margin-bottom: 10px;
text-overflow: ellipsis;
overflow: hidden;
}

.itemdate {
font-size: 0.9rem;
color: #502828;
margin-bottom: 5px;
}
.badge {
display: inline-block;
margin-bottom: 5px;
text-align: left; /* Align badge to the left */
}

.badge,
.itemdate {
font-size: 0.9rem;
color: #502828;
text-align: left;
width: auto;
margin-bottom: 5px;
}


.nItem div {
display: flex;
flex-direction: column;
align-items: flex-start;
}
.btn {
align-self: center;
margin-top: auto;
}

@media only screen and (max-width: 600px) {
.individualitem {
display: flex;
justify-content: center;
width: 100%;
}

.nItem {
width: 90%;
}
}
91 changes: 87 additions & 4 deletions src/pages/resources/ChanakyaBook.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,92 @@
import React from 'react'
import React, { useEffect, useState } from "react";
import axios from "axios";

const ChanakyaBook = () => {
const [books, setBooks] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

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

const fetchBooks = async () => {
try {
setLoading(true);
const response = await axios.get(
"https://www.googleapis.com/books/v1/volumes?q=chanakya+OR+arthashastra+OR+kautilya"
);

const fetchedBooks = response.data.items.map((book) => ({
title: book.volumeInfo.title,
authors: book.volumeInfo.authors,
description: book.volumeInfo.description,
thumbnail: book.volumeInfo.imageLinks?.thumbnail,
link: book.volumeInfo.previewLink,
}));

setBooks(fetchedBooks);
setLoading(false);
} catch (err) {
console.error("Error fetching books:", err);
setError("Failed to fetch books. Please try again later.");
setLoading(false);
}
};

const cardStyle = window.matchMedia("(max-width: 992px)").matches
? { width: "90%" }
: { width: "20rem" };
if (loading) return <div className="loading">Loading...</div>;
if (error) return <div className="error-message">{error}</div>;

return (
<div>ChanakyaBook</div>
)
}
<div className="container py-4">
<h1 className="text-center mb-4">Books on Chanakya & Arthashastra</h1>
<div className="row row-cols-1 row-cols-sm-2 row-cols-md-3 g-4">
{books.map((book, index) => (
<div key={index} className="col">
<div className="card h-100 shadow-sm" style={{ ...cardStyle }}>
{book.thumbnail && (
<img
src={book.thumbnail}
alt={book.title}
className="card-img-top"
style={{ height: "250px", objectFit: "contain" }}
/>
)}
<div className="card-body" style={{ padding: "10px" }}>
<h5 className="card-title" style={{ fontSize: "1rem" }}>
{book.title}
</h5>
{book.authors && (
<p className="card-text" style={{ fontSize: "0.9rem" }}>
By: {book.authors.join(", ")}
</p>
)}
{book.description && (
<p className="card-text" style={{ fontSize: "0.85rem" }}>
{book.description.substring(0, 80)}...
</p>
)}
</div>
<div className="card-footer" style={{ padding: "8px" }}>
<a
href={book.link}
target="_blank"
rel="noopener noreferrer"
className="btn btn-primary w-100"
style={{ fontSize: "0.9rem", padding: "6px" }}
>
Read More
</a>
</div>
</div>
</div>
))}
</div>
</div>
);
};

export default ChanakyaBook;
122 changes: 89 additions & 33 deletions src/pages/resources/ChanakyaNews.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import React, { useState, useEffect } from 'react';
import axios from 'axios';

import React, { useState, useEffect } from "react";
import axios from "axios";
import Slider from "react-slick";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import "../../css/ChanakyaNews.css";
const ChanakyaNews = () => {
const [news, setNews] = useState([]);
const [loading, setLoading] = useState(true);
Expand All @@ -13,74 +16,127 @@ const ChanakyaNews = () => {
const fetchNews = async () => {
try {
setLoading(true);
const rss2jsonEndpoint = 'https://api.rss2json.com/v1/api.json';
const googleNewsRSS = 'https://news.google.com/rss/search?q=archaryachanakya+OR+Arthashastra+OR+kautilya&hl=en-IN&gl=IN&ceid=IN:en';
const rss2jsonEndpoint = "https://api.rss2json.com/v1/api.json";
const googleNewsRSS =
"https://news.google.com/rss/search?q=archaryachanakya+OR+Arthashastra+OR+kautilya&hl=en-IN&gl=IN&ceid=IN:en";

const response = await axios.get(rss2jsonEndpoint, {
params: {
rss_url: googleNewsRSS,
api_key: import.meta.env.VITE_NEWS_API_KEY,
count: 60,
}
},
});

const newsItems = response.data.items.map(item => ({
const newsItems = response.data.items.map((item) => ({
title: item.title,
link: item.link,
pubDate: item.pubDate,
description: item.description
description: item.description,
}));

const categorizedNews = categorizeNews(newsItems);
setNews(categorizedNews);
setLoading(false);
} catch (err) {
setError('Failed to fetch news. Please try again later.');
setError("Failed to fetch news. Please try again later.");
setLoading(false);
}
};

const categorizeNews = (newsItems) => {
const categoryKeywords = {
economics: ['economy', 'finance', 'wealth', 'arthashastra', 'economic'],
politics: ['governance', 'leadership', 'strategy', 'political'],
history: ['history', 'ancient', 'mauryan', 'empire', 'historical'],
teachings: ['wisdom', 'teachings', 'philosophy', 'quotes'],
economics: ["economy", "finance", "wealth", "arthashastra", "economic"],
politics: ["governance", "leadership", "strategy", "political"],
history: ["history", "ancient", "mauryan", "empire", "historical"],
teachings: ["wisdom", "teachings", "philosophy", "quotes"],
};

return newsItems.map(item => {
const content = (item.title + ' ' + item.description).toLowerCase();
for (const [category, keywords] of Object.entries(categoryKeywords)) {
if (keywords.some(keyword => content.includes(keyword))) {
return { ...item, category };
return newsItems
.map((item) => {
const content = (item.title + " " + item.description).toLowerCase();
for (const [category, keywords] of Object.entries(categoryKeywords)) {
if (keywords.some((keyword) => content.includes(keyword))) {
return { ...item, category };
}
}
}
return null; // Exclude items that don't match any category
}).filter(item => item !== null);
return null; // Exclude items that don't match any category
})
.filter((item) => item !== null);
};

if (loading) return <div className="loading">Loading...</div>;
if (error) return <div className="error-message">{error}</div>;

const responsive = [
{
breakpoint: 1024,
settings: {
slidesToShow: 5,
},
},
{
breakpoint: 900,
settings: {
slidesToShow: 3,
},
},
{
breakpoint: 600,
settings: {
slidesToShow: 2,
},
},
{
breakpoint: 480,
settings: {
slidesToShow: 1,
},
},
];
// Slider settings for the multi-item carousel
const settings = {
dots: false,
infinite: true,
speed: 500,
slidesToShow: 4,
slidesToScroll: 1,
autoplay: true,
autoplaySpeed: 2000,
pauseOnHover: true,
arrows: false,
responsive,
};
return (
<div className="container">
<>
<h1 className="mb-4 text-center">Latest News on Aacharya Chanakya</h1>
<div className="row">
<Slider {...settings}>
{news.map((item, index) => (
<div key={index} className="col-md-6 col-lg-4 mb-4">
<div className="card w-full h-100 shadow-sm">
<div className="card-body d-flex flex-column">
<h5 className="card-title">{item.title}</h5>
<span className="badge bg-secondary mb-2 align-self-start">{item.category}</span>
<p className="text-muted mb-2">Published: {new Date(item.pubDate).toLocaleDateString()}</p>
<a href={item.link} target="_blank" rel="noopener noreferrer" className="btn btn-primary mt-auto">Read more</a>
<div key={index} className="individualitem">
<div className="nItem">
<h5 className="card-des">{item.title}</h5>
<div>
<span className="badge bg-secondary mb-2 align-self-start ">
{item.category}
</span>
<p className="itemdate ">
Published: {new Date(item.pubDate).toLocaleDateString()}
</p>
<a
href={item.link}
target="_blank"
rel="noopener noreferrer"
className="btn btn-secondary mt-auto"
>
Read more
</a>
</div>
</div>
</div>
))}
</div>
</div>
</Slider>
</>
);
};

export default ChanakyaNews;
export default ChanakyaNews;