Skip to content
Open
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
53 changes: 53 additions & 0 deletions public/sitemap.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/sitemap.xsl"?>
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<url>
<loc>https://mldl.study/</loc>
<lastmod>2025-11-04T12:23:46+00:00</lastmod>
<priority>1.00</priority>
</url>
<url>
<loc>https://mldl.study/prerequisites</loc>
<lastmod>2025-11-04T12:23:46+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://mldl.study/machinelearning</loc>
<lastmod>2025-11-04T12:23:46+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://mldl.study/deeplearning</loc>
<lastmod>2025-11-04T12:23:46+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://mldl.study/genai</loc>
<lastmod>2025-11-04T12:23:46+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://mldl.study/questionbank</loc>
<lastmod>2025-11-04T12:23:46+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://mldl.study/books</loc>
<lastmod>2025-11-04T12:23:46+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://mldl.study/privacy</loc>
<lastmod>2025-11-04T12:23:46+00:00</lastmod>
<priority>0.50</priority>
</url>
<url>
<loc>https://mldl.study/terms</loc>
<lastmod>2025-11-04T12:23:46+00:00</lastmod>
<priority>0.50</priority>
</url>
</urlset>
72 changes: 72 additions & 0 deletions public/sitemap.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<!-- sitemap file -->

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:s="http://www.sitemaps.org/schemas/sitemap/0.9">

<xsl:output method="html" encoding="UTF-8"/>

<xsl:template match="/">
<html>
<head>
<title>Sitemap – mldl.study</title>
<style>
body {
font-family: 'Inter', sans-serif;
background-color: #0f172a;
color: #f8fafc;
margin: 0;
padding: 2rem;
}
h1 {
color: #38bdf8;
text-align: center;
margin-bottom: 2rem;
}
table {
width: 100%;
border-collapse: collapse;
background-color: #1e293b;
border-radius: 12px;
overflow: hidden;
}
th, td {
padding: 12px 16px;
border-bottom: 1px solid #334155;
}
tr:hover {
background-color: #334155;
}
a {
color: #38bdf8;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
th {
text-align: left;
color: #94a3b8;
}
</style>
</head>
<body>
<h1>📍 Sitemap – mldl.study</h1>
<table>
<tr>
<th>URL</th>
<th>Last Modified</th>
</tr>
<!-- ✅ Notice the namespace 's:' prefix below -->
<xsl:for-each select="s:urlset/s:url">
<tr>
<td><a href="{s:loc}" target="_blank"><xsl:value-of select="s:loc"/></a></td>
<td><xsl:value-of select="s:lastmod"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
1 change: 0 additions & 1 deletion src/App.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* Remove the restrictive max-width and padding */
#root {
width: 100%;
margin: 0;
Expand Down
4 changes: 4 additions & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import Books from './components/Books';
import Journey from './components/Journey';
import QuestionBank from './components/QuestionBank';
import Search from './components/Search';
import PrivacyPolicy from './components/PrivacyPolicy';
import TermsOfUse from './components/TermsOfUse';
import ReactGA from 'react-ga4';
const trackingId = import.meta.env.VITE_APP_GA_TRACKING_ID;
if (trackingId) {
Expand All @@ -32,6 +34,8 @@ const App = () => {
<Route path="/journey" element={<Journey />} />
<Route path="/questionbank" element={<QuestionBank />} />
<Route path="/search" element={<Search />} />
<Route path="/privacy" element={<PrivacyPolicy />} />
<Route path="/terms" element={<TermsOfUse />} />
<Route path="*" element={<Error404 />} />
</Routes>
</div>
Expand Down
43 changes: 43 additions & 0 deletions src/components/BackToTopButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React, { useState, useEffect } from 'react';
import { ArrowUp } from 'lucide-react';

const BackToTopButton = () => {
const [isVisible, setIsVisible] = useState(false);

// Show button when page is scrolled down
const toggleVisibility = () => {
if (window.scrollY > 300) {
setIsVisible(true);
} else {
setIsVisible(false);
}
};

// Scroll to top smoothly
const scrollToTop = () => {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
};

useEffect(() => {
window.addEventListener('scroll', toggleVisibility);

return () => {
window.removeEventListener('scroll', toggleVisibility);
};
}, []);

return (
<button
className={`fixed bottom-8 right-8 z-50 p-3 rounded-full bg-gradient-to-r from-blue-500 to-indigo-600 text-white shadow-lg hover:from-blue-600 hover:to-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 dark:focus:ring-offset-gray-900 transition-all duration-300 ${isVisible ? 'opacity-100 scale-100' : 'opacity-0 scale-90'}`}
onClick={scrollToTop}
aria-label="Go to top"
>
<ArrowUp className="w-6 h-6" />
</button>
);
};

export default BackToTopButton;
67 changes: 33 additions & 34 deletions src/components/Books.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React, { useState, useEffect } from 'react';
import React, { useState } from 'react';
import ReactGA from 'react-ga4';
import { Book, ExternalLink, Search } from 'lucide-react';
import Navbar from './Navbar';
import Footer from './Footer';
import { Helmet } from 'react-helmet';
import useDarkMode from './useDarkMode';

const books = [
{ title: 'Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow', author: 'Aurélien Géron', link: 'https://www.bayanbox.ir/view/9006149947423722897/Hands-On-Machine-Learning-with-Scikit-Learn-Keras-and-TensorFlow.pdf', category: 'Machine Learning' },
Expand Down Expand Up @@ -31,23 +32,10 @@ const articles = [
const Books = () => {
ReactGA.send({ hitType: 'pageview', page: window.location.pathname });

const [darkMode, setDarkMode] = useState(false);
const [darkMode, toggleDarkMode] = useDarkMode();
const [searchTerm, setSearchTerm] = useState('');
const [selectedCategory, setSelectedCategory] = useState('all');

useEffect(() => {
const savedDarkMode = localStorage.getItem('darkMode') === 'true';
setDarkMode(savedDarkMode);
document.documentElement.classList.toggle('dark', savedDarkMode);
}, []);

const toggleDarkMode = () => {
const newDarkMode = !darkMode;
setDarkMode(newDarkMode);
document.documentElement.classList.toggle('dark', newDarkMode);
localStorage.setItem('darkMode', newDarkMode);
};

const categories = ['all', ...new Set([...books, ...articles].map(item => item.category))];

const filteredBooks = books.filter(book =>
Expand Down Expand Up @@ -102,15 +90,18 @@ const Books = () => {
<div className="flex flex-col md:flex-row gap-4 mb-8">
<div className="relative flex-1">
<div className="absolute inset-y-0 left-3 flex items-center pointer-events-none">
<Search className="w-5 h-5 text-gray-400" />
<Search className={`w-5 h-5 ${darkMode ? 'text-gray-500' : 'text-gray-400'}`} />
</div>
<input
type="text"
placeholder="Search by title or author..."
className="w-full pl-10 pr-4 py-3 rounded-xl border border-gray-200 dark:border-gray-700
bg-white dark:bg-gray-800 text-gray-900 dark:text-white
className={`w-full pl-10 pr-4 py-3 rounded-xl border
${darkMode
? 'border-gray-700 bg-gray-800 text-white placeholder-gray-400'
: 'border-gray-200 bg-white text-gray-900 placeholder-gray-400'
}
shadow-sm focus:ring-2 focus:ring-blue-600 focus:border-transparent
transition-all duration-200"
transition-all duration-200`}
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
Expand All @@ -120,10 +111,12 @@ const Books = () => {
<button
key={category}
onClick={() => setSelectedCategory(category)}
className={`px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap
className={`px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap transition-all
${selectedCategory === category
? 'bg-blue-600 text-white'
: 'bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-300 dark:hover:bg-gray-600'
: darkMode
? 'bg-gray-800 text-gray-300 hover:bg-gray-700 border border-gray-700'
: 'bg-gray-200 text-gray-700 hover:bg-gray-300'
}`}
>
{category.charAt(0).toUpperCase() + category.slice(1)}
Expand All @@ -142,16 +135,19 @@ const Books = () => {
{filteredBooks.map((book, index) => (
<div
key={index}
className={`bg-white dark:bg-gray-800 rounded-xl shadow-sm hover:shadow-md
transition-all duration-200 border border-gray-200 dark:border-gray-700`}
className={`rounded-xl shadow-sm hover:shadow-md transition-all duration-200
${darkMode
? 'bg-gray-800 border border-gray-700'
: 'bg-white border border-gray-200'
}`}
>
<div className="p-6">
<div className="flex items-start justify-between">
<div className="flex-1">
<h3 className="font-semibold text-lg mb-2 line-clamp-2">
<h3 className={`font-semibold text-lg mb-2 line-clamp-2 ${darkMode ? 'text-white' : 'text-gray-900'}`}>
{book.title}
</h3>
<p className="text-gray-600 dark:text-gray-400 text-sm mb-4">
<p className={`text-sm mb-4 ${darkMode ? 'text-gray-400' : 'text-gray-600'}`}>
by {book.author}
</p>
</div>
Expand All @@ -163,7 +159,7 @@ const Books = () => {
href={book.link}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 text-blue-600 dark:text-blue-400 hover:underline"
className={`inline-flex items-center gap-2 hover:underline ${darkMode ? 'text-blue-400' : 'text-blue-600'}`}
>
<span>Read Book</span>
<ExternalLink className="w-4 h-4" />
Expand All @@ -186,16 +182,19 @@ const Books = () => {
{filteredArticles.map((article, index) => (
<div
key={index}
className={`bg-white dark:bg-gray-800 rounded-xl shadow-sm hover:shadow-md
transition-all duration-200 border border-gray-200 dark:border-gray-700`}
className={`rounded-xl shadow-sm hover:shadow-md transition-all duration-200
${darkMode
? 'bg-gray-800 border border-gray-700'
: 'bg-white border border-gray-200'
}`}
>
<div className="p-6">
<div className="flex items-start justify-between">
<div className="flex-1">
<h3 className="font-semibold text-lg mb-2 line-clamp-2">
<h3 className={`font-semibold text-lg mb-2 line-clamp-2 ${darkMode ? 'text-white' : 'text-gray-900'}`}>
{article.title}
</h3>
<p className="text-gray-600 dark:text-gray-400 text-sm mb-4">
<p className={`text-sm mb-4 ${darkMode ? 'text-gray-400' : 'text-gray-600'}`}>
by {article.author}
</p>
</div>
Expand All @@ -207,7 +206,7 @@ const Books = () => {
href={article.link}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 text-blue-600 dark:text-blue-400 hover:underline"
className={`inline-flex items-center gap-2 hover:underline ${darkMode ? 'text-blue-400' : 'text-blue-600'}`}
>
<span>Read Article</span>
<ExternalLink className="w-4 h-4" />
Expand All @@ -222,8 +221,8 @@ const Books = () => {
{filteredBooks.length === 0 && filteredArticles.length === 0 && (
<div className="text-center py-12">
<div className="text-5xl mb-4">🔍</div>
<h3 className="text-xl font-semibold mb-2">No resources found</h3>
<p className="text-gray-600 dark:text-gray-400">
<h3 className={`text-xl font-semibold mb-2 ${darkMode ? 'text-white' : 'text-gray-900'}`}>No resources found</h3>
<p className={darkMode ? 'text-gray-400' : 'text-gray-600'}>
Try adjusting your search or filter to find what you're looking for.
</p>
</div>
Expand All @@ -236,4 +235,4 @@ const Books = () => {
);
};

export default Books;
export default Books;
Loading