diff --git a/src/client/src/App.css b/src/client/src/App.css
index 064292a..74b5e05 100644
--- a/src/client/src/App.css
+++ b/src/client/src/App.css
@@ -36,119 +36,3 @@
transform: rotate(360deg);
}
}
-
-/* LeetCode-like styling for ProblemPage */
-.lcw-problem-page {
- max-width: 800px;
- margin: 32px auto;
- background: #fff;
- border-radius: 12px;
- box-shadow: 0 2px 16px rgba(0,0,0,0.08);
- padding: 32px;
- font-family: 'Segoe UI', 'Roboto', 'Arial', sans-serif;
-}
-
-.lcw-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 18px;
-}
-
-.lcw-link {
- color: #ffa116;
- text-decoration: none;
- font-weight: 500;
- border-bottom: 1px dashed #ffa116;
- transition: border-bottom 0.2s;
-}
-.lcw-link:hover {
- border-bottom: 2px solid #ffa116;
-}
-
-.lcw-meta {
- display: flex;
- gap: 18px;
- margin-bottom: 24px;
- font-size: 16px;
-}
-
-.lcw-meta-item {
- color: #555;
-}
-
-.lcw-difficulty {
- padding: 4px 12px;
- border-radius: 8px;
- font-weight: bold;
- color: #fff;
-}
-.lcw-difficulty-easy {
- background: #43a047;
-}
-.lcw-difficulty-medium {
- background: #ffa116;
-}
-.lcw-difficulty-hard {
- background: #d32f2f;
-}
-.lcw-difficulty-unknown {
- background: #888;
-}
-
-.lcw-section-title {
- margin-top: 32px;
- margin-bottom: 12px;
- font-size: 20px;
- color: #222;
- font-weight: 600;
-}
-
-.lcw-table {
- width: 100%;
- border-collapse: collapse;
- margin-bottom: 24px;
- background: #fafbfc;
- border-radius: 8px;
- overflow: hidden;
-}
-
-.lcw-table th, .lcw-table td {
- padding: 12px 10px;
- border-bottom: 1px solid #eee;
- text-align: left;
-}
-
-.lcw-table th {
- background: #f6f8fa;
- font-weight: 600;
- color: #333;
-}
-
-.lcw-tag {
- display: inline-block;
- background: #e3e6ea;
- color: #444;
- padding: 4px 10px;
- border-radius: 6px;
- font-size: 14px;
- font-weight: 500;
-}
-
-.lcw-company {
- display: inline-block;
- background: #f5f5f5;
- color: #222;
- margin: 2px 6px 2px 0;
- padding: 4px 10px;
- border-radius: 6px;
- font-size: 14px;
- border: 1px solid #eee;
-}
-
-.lcw-loading, .lcw-error {
- text-align: center;
- margin-top: 40px;
- font-size: 18px;
- color: #d32f2f;
-}
\ No newline at end of file
diff --git a/src/client/src/App.js b/src/client/src/App.js
index 4e81d85..10f3213 100644
--- a/src/client/src/App.js
+++ b/src/client/src/App.js
@@ -2,15 +2,19 @@ import "./App.css";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Main from "./components/layout/Main";
import ProblemPage from "./components/problems/ProblemPage";
+import Header from "./components/layout/Header";
+import Footer from "./components/layout/Footer";
function App() {
return (
@@ -26,9 +35,14 @@ const Body = ({ problems, loading, error, filters }) => {
);
};
-export default Body;
+export default Body;
\ No newline at end of file
diff --git a/src/client/src/components/layout/Header.js b/src/client/src/components/layout/Header.js
index fcdfe21..7fc2f69 100644
--- a/src/client/src/components/layout/Header.js
+++ b/src/client/src/components/layout/Header.js
@@ -1,11 +1,14 @@
import React from "react";
import "../../styles/layout/Header.css";
+import { Link } from "react-router-dom";
const Header = () => {
return (
);
diff --git a/src/client/src/components/layout/Main.js b/src/client/src/components/layout/Main.js
index 429a4e3..46136d3 100644
--- a/src/client/src/components/layout/Main.js
+++ b/src/client/src/components/layout/Main.js
@@ -1,9 +1,7 @@
import React, { useState, useEffect, useMemo } from "react";
import { fetchProblems } from "../../services/api";
-import Header from "./Header";
import Nav from "./Nav";
import Body from "./Body";
-import Footer from "./Footer";
import "../../styles/layout/Main.css";
const Main = () => {
@@ -15,14 +13,25 @@ const Main = () => {
timePeriod: "",
difficulty: "",
});
+ const [currentPage, setCurrentPage] = useState(1);
+ const [totalPages, setTotalPages] = useState(1);
+
+ const PROBLEMS_PER_PAGE = 50;
useEffect(() => {
const loadProblems = async () => {
setLoading(true);
try {
- const data = await fetchProblems();
+ const data = await fetchProblems(currentPage, PROBLEMS_PER_PAGE, filters);
setProblems(data);
setError(null);
+
+ // Estimate total pages based on response
+ if (data.length < PROBLEMS_PER_PAGE) {
+ setTotalPages(currentPage);
+ } else {
+ setTotalPages(currentPage + 1);
+ }
} catch (err) {
setError("Failed to fetch problems. Please try again later.");
setProblems([]);
@@ -32,7 +41,7 @@ const Main = () => {
};
loadProblems();
- }, []);
+ }, [currentPage, filters]);
// Extract unique company names from problems
const companies = useMemo(() => {
@@ -49,11 +58,17 @@ const Main = () => {
const handleFilterChange = (newFilters) => {
setFilters(newFilters);
+ setCurrentPage(1); // Reset to first page when filters change
+ };
+
+ const handlePageChange = (page) => {
+ setCurrentPage(page);
+ // Scroll to top when page changes
+ window.scrollTo({ top: 0, behavior: 'smooth' });
};
return (
-
);
};
-export default Main;
+export default Main;
\ No newline at end of file
diff --git a/src/client/src/components/layout/Pagination.js b/src/client/src/components/layout/Pagination.js
new file mode 100644
index 0000000..2458d84
--- /dev/null
+++ b/src/client/src/components/layout/Pagination.js
@@ -0,0 +1,75 @@
+// components/Pagination.js
+import React from "react";
+import "../../styles/layout/Pagination.css";
+
+const Pagination = ({ currentPage, totalPages, onPageChange }) => {
+ const getPageNumbers = () => {
+ const pages = [];
+ const maxVisiblePages = 5;
+
+ let startPage = Math.max(1, currentPage - Math.floor(maxVisiblePages / 2));
+ let endPage = Math.min(totalPages, startPage + maxVisiblePages - 1);
+
+ // Adjust start page if we're near the end
+ if (endPage - startPage + 1 < maxVisiblePages) {
+ startPage = Math.max(1, endPage - maxVisiblePages + 1);
+ }
+
+ for (let i = startPage; i <= endPage; i++) {
+ pages.push(i);
+ }
+
+ return pages;
+ };
+
+ if (totalPages <= 1) return null;
+
+ return (
+
+ {/* First Page Button */}
+
+
+ {/* Previous Page Button */}
+
+
+ {/* Page Numbers */}
+
+ {getPageNumbers().map(page => (
+
+ ))}
+
+
+ {/* Next Page Button */}
+
+
+ );
+};
+
+export default Pagination;
\ No newline at end of file
diff --git a/src/client/src/components/problems/ProblemCard.js b/src/client/src/components/problems/ProblemCard.js
index ff81d28..d715b53 100644
--- a/src/client/src/components/problems/ProblemCard.js
+++ b/src/client/src/components/problems/ProblemCard.js
@@ -4,6 +4,7 @@ import {
getDifficultyClass,
} from "../../constants/difficulty";
import "../../styles/components/ProblemCard.css";
+import { Link } from "react-router-dom";
const TIME_PERIOD_LABELS = {
"thirty-days": "Last 30 Days",
@@ -43,9 +44,7 @@ const ProblemCard = ({ problem }) => {
{difficultyText}
diff --git a/src/client/src/components/problems/ProblemPage.js b/src/client/src/components/problems/ProblemPage.js
index fd0fa56..7d4ccbd 100644
--- a/src/client/src/components/problems/ProblemPage.js
+++ b/src/client/src/components/problems/ProblemPage.js
@@ -1,6 +1,7 @@
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { getProblemById } from "../../services/api";
+import "../../styles/components/ProblemPage.css";
const tagOrder = ["thirty-days", "three-months", "six-months", "one-year", "all"];
diff --git a/src/client/src/services/api.js b/src/client/src/services/api.js
index 3f4137e..b57069a 100644
--- a/src/client/src/services/api.js
+++ b/src/client/src/services/api.js
@@ -1,7 +1,25 @@
+// services/api.js
const API_BASE_URL = "http://localhost:5164/api";
-export const fetchProblems = async () => {
- const response = await fetch(`${API_BASE_URL}/problems`);
+export const fetchProblems = async (page = 1, limit = 50, filters = {}) => {
+ const skip = (page - 1) * limit;
+ const params = new URLSearchParams({
+ skip: skip.toString(),
+ limit: limit.toString()
+ });
+
+ // Add filter parameters if they exist
+ if (filters.company) {
+ params.append('companies', filters.company);
+ }
+ if (filters.difficulty) {
+ params.append('difficulties', filters.difficulty);
+ }
+ if (filters.timePeriod) {
+ params.append('tags', filters.timePeriod);
+ }
+
+ const response = await fetch(`${API_BASE_URL}/problems?${params}`);
if (!response.ok) {
throw new Error(`Network response was not ok: ${response.status}`);
}
@@ -14,4 +32,4 @@ export const getProblemById = async (id) => {
throw new Error(`Failed to fetch problem #${id}`);
}
return await response.json();
-};
+};
\ No newline at end of file
diff --git a/src/client/src/styles/components/FilterOptions.css b/src/client/src/styles/components/FilterOptions.css
index 0a17f25..a5ff42d 100644
--- a/src/client/src/styles/components/FilterOptions.css
+++ b/src/client/src/styles/components/FilterOptions.css
@@ -1,72 +1,180 @@
.filter-options {
display: flex;
- gap: 1.5rem;
+ gap: 2rem;
align-items: flex-end;
flex-wrap: wrap;
- padding: 1rem 0;
+ padding: 1.5rem 0;
+ position: relative;
+ z-index: 10;
}
.filter-group {
display: flex;
flex-direction: column;
- gap: 0.5rem;
- min-width: 200px;
+ gap: 0.75rem;
+ min-width: 220px;
+ position: relative;
+ z-index: 1000; /* Ensure high z-index for dropdown */
}
.filter-group label {
- font-size: 0.9rem;
- color: #666;
- font-weight: 500;
+ font-size: 0.85rem;
+ color: #4a5568;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
}
.filter-group select {
- padding: 0.5rem;
- border: 1px solid #ddd;
- border-radius: 4px;
+ padding: 0.75rem 1rem;
+ border: 2px solid #e2e8f0;
+ border-radius: 10px;
background-color: white;
- font-size: 0.9rem;
- color: #333;
+ font-size: 0.95rem;
+ color: #2d3748;
+ cursor: pointer;
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+ appearance: none;
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%234a5568'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E");
+ background-repeat: no-repeat;
+ background-position: right 1rem center;
+ background-size: 1rem;
+ padding-right: 2.5rem;
+ font-weight: 500;
+ position: relative;
+ z-index: 1001; /* Higher z-index for the select element */
+}
+
+/* Ensure dropdown options are visible */
+.filter-group select option {
+ background: white;
+ color: #2d3748;
+ padding: 12px 16px;
+ font-size: 0.95rem;
+ border-bottom: 1px solid #f1f5f9;
+ position: relative;
+ z-index: 10000; /* Very high z-index for options */
+}
+
+.filter-group select option:hover {
+ background-color: #f0f7ff;
+ color: #0066cc;
+}
+
+.filter-group select option:checked {
+ background-color: #0066cc;
+ color: white;
+}
+
+.filter-group select:focus {
+ outline: none;
+ border-color: #0066cc;
+ box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1);
+ background-color: white;
+ z-index: 1002; /* Even higher when focused */
+}
+
+/* Style the dropdown container */
+.filter-group select {
+ z-index: 1001;
+}
+
+/* Ensure the dropdown appears above other elements */
+.filter-group {
+ position: relative;
+}
+
+/* Fix for dropdown visibility */
+select {
+ position: relative;
}
-.filter-group select:disabled {
- background-color: #f5f5f5;
- cursor: not-allowed;
+/* Additional styles to ensure dropdown visibility */
+.filter-options * {
+ box-sizing: border-box;
}
+/* Company dropdown specific fixes */
+#company {
+ min-height: 48px;
+ max-height: 200px; /* Limit height if needed */
+}
+
+/* Ensure the nav has proper z-index */
+.nav {
+ background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
+ border-bottom: 1px solid #e2e8f0;
+ padding: 0;
+ box-shadow: 0 2px 20px rgba(0, 0, 0, 0.06);
+ position: relative;
+ z-index: 100;
+}
+
+.nav-content {
+ max-width: 1200px;
+ margin: 0 auto;
+ padding: 0 1.5rem;
+ position: relative;
+ z-index: 101;
+}
+
+/* Clear filters button */
.clear-filters {
- padding: 0.5rem 1rem;
- background-color: #dc3545;
+ padding: 0.75rem 1.5rem;
+ background: linear-gradient(135deg, #dc3545, #c82333);
color: white;
border: none;
- border-radius: 4px;
+ border-radius: 10px;
cursor: pointer;
font-size: 0.9rem;
+ font-weight: 600;
height: fit-content;
-}
-
-.clear-filters:hover {
- background-color: #c82333;
-}
-
-.clear-filters:disabled {
- background-color: #f5f5f5;
- color: #999;
- cursor: not-allowed;
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+ box-shadow: 0 2px 8px rgba(220, 53, 69, 0.3);
+ position: relative;
+ z-index: 100;
}
/* Responsive adjustments */
@media (max-width: 768px) {
.filter-options {
flex-direction: column;
- gap: 1rem;
+ gap: 1.25rem;
+ padding: 1.25rem 0;
+ z-index: 1000;
}
.filter-group {
width: 100%;
min-width: unset;
+ z-index: 1001;
+ }
+
+ .filter-group select {
+ width: 100%;
+ z-index: 1002;
}
.clear-filters {
width: 100%;
+ margin-top: 0.5rem;
+ z-index: 100;
}
+}
+
+/* Emergency fix - if dropdown still doesn't show */
+.filter-group select {
+ transform: translateZ(0); /* Force hardware acceleration */
+}
+
+/* Alternative: Increase the size of the dropdown */
+.filter-group select {
+ min-height: 48px;
+}
+
+/* Make sure the dropdown has enough space */
+.filter-group {
+ margin-bottom: 0;
}
\ No newline at end of file
diff --git a/src/client/src/styles/components/ProblemCard.css b/src/client/src/styles/components/ProblemCard.css
index c3f30b5..97027f8 100644
--- a/src/client/src/styles/components/ProblemCard.css
+++ b/src/client/src/styles/components/ProblemCard.css
@@ -1,96 +1,269 @@
.problem-card {
- background: white;
- border-radius: 8px;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
- padding: 1.5rem;
- transition: transform 0.2s ease, box-shadow 0.2s ease;
+ background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
+ border-radius: 12px;
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
+ padding: 1.75rem;
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+ border: 1px solid rgba(255, 255, 255, 0.8);
+ position: relative;
+ overflow: hidden;
+}
+
+.problem-card::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 3px;
+ background: linear-gradient(90deg, #0066cc, #0099ff);
+ transform: scaleX(0);
+ transition: transform 0.3s ease;
}
.problem-card:hover {
- transform: translateY(-2px);
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
+ transform: translateY(-4px);
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
+}
+
+.problem-card:hover::before {
+ transform: scaleX(1);
}
.problem-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
- margin-bottom: 1rem;
+ margin-bottom: 1.25rem;
+ gap: 1rem;
}
.problem-header h3 {
margin: 0;
- font-size: 1.1rem;
+ font-size: 1.25rem;
flex: 1;
- padding-right: 1rem;
+ font-weight: 600;
+ line-height: 1.4;
}
.problem-header a {
- color: #1a1a1a;
+ color: #1a202c;
text-decoration: none;
+ background: linear-gradient(90deg, #1a202c, #2d3748);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+ transition: all 0.3s ease;
+ position: relative;
+}
+
+.problem-header a::after {
+ content: '';
+ position: absolute;
+ bottom: -2px;
+ left: 0;
+ width: 0;
+ height: 2px;
+ background: linear-gradient(90deg, #0066cc, #0099ff);
+ transition: width 0.3s ease;
}
.problem-header a:hover {
- color: #0066cc;
+ background: linear-gradient(90deg, #0066cc, #0099ff);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.problem-header a:hover::after {
+ width: 100%;
}
.difficulty {
- padding: 0.25rem 0.75rem;
- border-radius: 12px;
- font-size: 0.85rem;
- font-weight: 500;
+ padding: 0.4rem 1rem;
+ border-radius: 20px;
+ font-size: 0.8rem;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+ white-space: nowrap;
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
+ border: 1px solid rgba(255, 255, 255, 0.3);
}
.difficulty.easy {
- background-color: #e7f6e7;
- color: #2cbb5d;
+ background: linear-gradient(135deg, #43a047, #4caf50);
+ color: white;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.difficulty.medium {
- background-color: #fff7e6;
- color: #ffa116;
+ background: linear-gradient(135deg, #ffa116, #ffb74d);
+ color: white;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.difficulty.hard {
- background-color: #ffe6e6;
- color: #ff375f;
+ background: linear-gradient(135deg, #d32f2f, #f44336);
+ color: white;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.problem-stats {
display: flex;
- gap: 1rem;
- margin-bottom: 1rem;
+ gap: 1.5rem;
+ margin-bottom: 1.25rem;
font-size: 0.9rem;
- color: #666;
+}
+
+.problem-stats span {
+ display: flex;
+ align-items: center;
+ color: #4a5568;
+ font-weight: 500;
+ position: relative;
+}
+
+.problem-stats span::before {
+ content: '';
+ display: inline-block;
+ width: 4px;
+ height: 4px;
+ border-radius: 50%;
+ background: #cbd5e0;
+ margin-right: 0.5rem;
+}
+
+.problem-stats span:first-child::before {
+ display: none;
+}
+
+.acceptance {
+ color: #2d3748;
+ font-weight: 600;
+}
+
+.frequency {
+ color: #4a5568;
}
.problem-companies {
- border-top: 1px solid #eee;
- padding-top: 1rem;
+ border-top: 1px solid #e2e8f0;
+ padding-top: 1.25rem;
+ margin-top: 1rem;
}
.problem-companies small {
display: block;
- margin-bottom: 0.5rem;
- color: #666;
+ margin-bottom: 0.75rem;
+ color: #718096;
+ font-weight: 600;
+ font-size: 0.8rem;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
}
.company-tags {
display: flex;
flex-wrap: wrap;
- gap: 0.5rem;
+ gap: 0.6rem;
}
.company-tag {
- background: #f5f5f5;
- padding: 0.25rem 0.75rem;
- border-radius: 12px;
- font-size: 0.85rem;
+ background: linear-gradient(135deg, #ffffff, #f7fafc);
+ padding: 0.5rem 1rem;
+ border-radius: 10px;
+ font-size: 0.8rem;
display: flex;
align-items: center;
- gap: 0.25rem;
+ gap: 0.4rem;
+ border: 1px solid #e2e8f0;
+ transition: all 0.2s ease;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
+ font-weight: 500;
+ color: #2d3748;
+}
+
+.company-tag:hover {
+ transform: translateY(-1px);
+ box-shadow: 0 3px 8px rgba(0, 0, 0, 0.1);
+ border-color: #ffa116;
+ background: linear-gradient(135deg, #fffaf0, #fffbeb);
+}
+
+.company-name {
+ font-weight: 600;
+ color: #2d3748;
}
.recent-indicator {
- font-size: 0.8rem;
+ font-size: 0.7rem;
+ animation: pulse 2s infinite;
+}
+
+@keyframes pulse {
+ 0%, 100% {
+ opacity: 1;
+ transform: scale(1);
+ }
+ 50% {
+ opacity: 0.7;
+ transform: scale(1.1);
+ }
+}
+
+/* Responsive Design */
+@media (max-width: 768px) {
+ .problem-card {
+ padding: 1.25rem;
+ margin: 0.5rem;
+ }
+
+ .problem-header {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 0.75rem;
+ }
+
+ .problem-header h3 {
+ font-size: 1.1rem;
+ padding-right: 0;
+ }
+
+ .difficulty {
+ align-self: flex-start;
+ }
+
+ .problem-stats {
+ flex-direction: column;
+ gap: 0.5rem;
+ }
+
+ .problem-stats span::before {
+ display: none;
+ }
+
+ .company-tags {
+ gap: 0.4rem;
+ }
+
+ .company-tag {
+ padding: 0.4rem 0.8rem;
+ font-size: 0.75rem;
+ }
+}
+
+/* Animation for card entrance */
+@keyframes cardEntrance {
+ from {
+ opacity: 0;
+ transform: translateY(20px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+.problem-card {
+ animation: cardEntrance 0.6s ease-out;
}
\ No newline at end of file
diff --git a/src/client/src/styles/components/ProblemPage.css b/src/client/src/styles/components/ProblemPage.css
new file mode 100644
index 0000000..3ddf68b
--- /dev/null
+++ b/src/client/src/styles/components/ProblemPage.css
@@ -0,0 +1,271 @@
+.lcw-problem-page {
+ max-width: 900px;
+ margin: 32px auto;
+ background: #fff;
+ border-radius: 16px;
+ box-shadow: 0 4px 24px rgba(0, 0, 0, 0.1);
+ padding: 40px;
+ font-family: 'Segoe UI', 'Roboto', 'Arial', sans-serif;
+ color: #2d3748;
+ line-height: 1.6;
+}
+
+/* Header Section */
+.lcw-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+ margin-bottom: 24px;
+ border-bottom: 2px solid #f1f5f9;
+ padding-bottom: 20px;
+}
+
+.lcw-header h2 {
+ margin: 0;
+ font-size: 28px;
+ font-weight: 700;
+ color: #1a202c;
+ line-height: 1.3;
+ flex: 1;
+}
+
+.lcw-link {
+ color: #ffa116;
+ text-decoration: none;
+ font-weight: 600;
+ padding: 8px 16px;
+ border: 2px solid #ffa116;
+ border-radius: 8px;
+ transition: all 0.3s ease;
+ font-size: 14px;
+ white-space: nowrap;
+ margin-left: 20px;
+}
+
+.lcw-link:hover {
+ background: #ffa116;
+ color: white;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(255, 161, 22, 0.3);
+}
+
+/* Meta Information */
+.lcw-meta {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 16px;
+ margin-bottom: 32px;
+ padding: 20px;
+ background: #f8fafc;
+ border-radius: 12px;
+ border-left: 4px solid #ffa116;
+}
+
+.lcw-meta-item {
+ color: #4a5568;
+ font-size: 15px;
+ font-weight: 500;
+}
+
+.lcw-difficulty {
+ padding: 6px 16px;
+ border-radius: 12px;
+ font-weight: 600;
+ color: #fff;
+ font-size: 14px;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+.lcw-difficulty-easy {
+ background: linear-gradient(135deg, #43a047, #4caf50);
+ box-shadow: 0 2px 8px rgba(67, 160, 71, 0.3);
+}
+
+.lcw-difficulty-medium {
+ background: linear-gradient(135deg, #ffa116, #ffb74d);
+ box-shadow: 0 2px 8px rgba(255, 161, 22, 0.3);
+}
+
+.lcw-difficulty-hard {
+ background: linear-gradient(135deg, #d32f2f, #f44336);
+ box-shadow: 0 2px 8px rgba(211, 47, 47, 0.3);
+}
+
+.lcw-difficulty-unknown {
+ background: linear-gradient(135deg, #718096, #a0aec0);
+}
+
+/* Section Title */
+.lcw-section-title {
+ margin: 40px 0 20px 0;
+ font-size: 22px;
+ color: #1a202c;
+ font-weight: 700;
+ position: relative;
+ padding-bottom: 12px;
+}
+
+.lcw-section-title::after {
+ content: '';
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ width: 60px;
+ height: 3px;
+ background: linear-gradient(90deg, #ffa116, #ffd54f);
+ border-radius: 2px;
+}
+
+/* Table Styling */
+.lcw-table {
+ width: 100%;
+ border-collapse: separate;
+ border-spacing: 0;
+ margin-bottom: 32px;
+ background: #fff;
+ border-radius: 12px;
+ overflow: hidden;
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
+}
+
+.lcw-table th {
+ background: linear-gradient(135deg, #1a202c, #2d3748);
+ color: white;
+ font-weight: 600;
+ padding: 16px 20px;
+ text-align: left;
+ font-size: 15px;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+.lcw-table td {
+ padding: 20px;
+ border-bottom: 1px solid #e2e8f0;
+ background: #fff;
+ transition: background-color 0.2s ease;
+}
+
+.lcw-table tr:last-child td {
+ border-bottom: none;
+}
+
+.lcw-table tr:hover td {
+ background: #f7fafc;
+}
+
+/* Tag Styling */
+.lcw-tag {
+ display: inline-block;
+ background: linear-gradient(135deg, #e2e8f0, #edf2f7);
+ color: #2d3748;
+ padding: 8px 16px;
+ border-radius: 8px;
+ font-size: 13px;
+ font-weight: 600;
+ text-transform: capitalize;
+ border: 1px solid #cbd5e0;
+ min-width: 100px;
+ text-align: center;
+}
+
+/* Company Tags */
+.lcw-company {
+ display: inline-block;
+ background: linear-gradient(135deg, #ffffff, #f7fafc);
+ color: #2d3748;
+ margin: 4px 8px 4px 0;
+ padding: 6px 14px;
+ border-radius: 8px;
+ font-size: 13px;
+ font-weight: 500;
+ border: 1px solid #e2e8f0;
+ transition: all 0.2s ease;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
+}
+
+.lcw-company:hover {
+ transform: translateY(-1px);
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+ border-color: #ffa116;
+ background: linear-gradient(135deg, #fffaf0, #fffbeb);
+}
+
+/* Loading and Error States */
+.lcw-loading, .lcw-error {
+ text-align: center;
+ margin-top: 60px;
+ font-size: 18px;
+ padding: 40px;
+ border-radius: 12px;
+}
+
+.lcw-loading {
+ color: #4a5568;
+ background: #f7fafc;
+ border: 2px dashed #cbd5e0;
+}
+
+.lcw-error {
+ color: #e53e3e;
+ background: #fed7d7;
+ border: 2px solid #feb2b2;
+ font-weight: 600;
+}
+
+/* Responsive Design */
+@media (max-width: 768px) {
+ .lcw-problem-page {
+ margin: 16px;
+ padding: 24px;
+ border-radius: 12px;
+ }
+
+ .lcw-header {
+ flex-direction: column;
+ align-items: flex-start;
+ }
+
+ .lcw-link {
+ margin: 16px 0 0 0;
+ align-self: flex-start;
+ }
+
+ .lcw-meta {
+ flex-direction: column;
+ gap: 12px;
+ align-items: flex-start;
+ }
+
+ .lcw-table {
+ font-size: 14px;
+ }
+
+ .lcw-table th,
+ .lcw-table td {
+ padding: 12px 8px;
+ }
+
+ .lcw-company {
+ font-size: 12px;
+ padding: 4px 10px;
+ margin: 2px 4px 2px 0;
+ }
+}
+
+/* Animation for page load */
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ transform: translateY(20px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+.lcw-problem-page {
+ animation: fadeIn 0.6s ease-out;
+}
\ No newline at end of file
diff --git a/src/client/src/styles/layout/Body.css b/src/client/src/styles/layout/Body.css
index 7824269..c98c329 100644
--- a/src/client/src/styles/layout/Body.css
+++ b/src/client/src/styles/layout/Body.css
@@ -46,4 +46,9 @@
.error-message button:hover {
background-color: #c82333;
-}
\ No newline at end of file
+}
+
+/* Add to styles/layout/Body.css */
+.body-content {
+ min-height: 60vh;
+}
diff --git a/src/client/src/styles/layout/Footer.css b/src/client/src/styles/layout/Footer.css
index aa1159f..9e9425a 100644
--- a/src/client/src/styles/layout/Footer.css
+++ b/src/client/src/styles/layout/Footer.css
@@ -1,19 +1,64 @@
.footer {
- background-color: #1a1a1a;
+ background: #1a1a1a;
color: white;
- padding: 1rem 0;
+ padding: 1.5rem 0;
margin-top: auto;
+ border-top: 1px solid #2d2d2d;
}
.footer-content {
max-width: 1200px;
margin: 0 auto;
- padding: 0 1rem;
+ padding: 0 2rem;
text-align: center;
}
.footer p {
margin: 0;
- font-size: 0.9rem;
- opacity: 0.8;
+ font-size: 0.95rem;
+ color: #a0a0a0;
+ font-weight: 400;
+ letter-spacing: 0.5px;
+ transition: color 0.2s ease;
+}
+
+.footer p:hover {
+ color: #d0d0d0;
+}
+
+/* Optional: Add a subtle top border accent */
+.footer {
+ position: relative;
+}
+
+.footer::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 100px;
+ height: 2px;
+ background: linear-gradient(90deg, transparent, #ffa116, transparent);
+}
+
+/* Responsive Design */
+@media (max-width: 768px) {
+ .footer {
+ padding: 1.25rem 0;
+ }
+
+ .footer-content {
+ padding: 0 1rem;
+ }
+
+ .footer p {
+ font-size: 0.9rem;
+ }
+}
+
+@media (max-width: 480px) {
+ .footer p {
+ font-size: 0.85rem;
+ }
}
\ No newline at end of file
diff --git a/src/client/src/styles/layout/Header.css b/src/client/src/styles/layout/Header.css
index 6648f4d..7796726 100644
--- a/src/client/src/styles/layout/Header.css
+++ b/src/client/src/styles/layout/Header.css
@@ -1,22 +1,229 @@
.header {
width: 100%;
- background-color: #1a1a1a;
+ background: linear-gradient(135deg, #1a1a1a 0%, #2d1b69 50%, #1a1a1a 100%);
color: white;
- padding: 1rem 0;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+ padding: 1.25rem 0;
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
+ position: relative;
+ overflow: hidden;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+}
+
+.header::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background:
+ radial-gradient(circle at 20% 80%, rgba(255, 161, 22, 0.1) 0%, transparent 50%),
+ radial-gradient(circle at 80% 20%, rgba(0, 102, 204, 0.1) 0%, transparent 50%),
+ radial-gradient(circle at 40% 40%, rgba(67, 160, 71, 0.05) 0%, transparent 50%);
+ pointer-events: none;
+}
+
+.header::after {
+ content: '';
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 1px;
+ background: linear-gradient(90deg,
+ transparent 0%,
+ rgba(255, 161, 22, 0.6) 25%,
+ rgba(0, 102, 204, 0.6) 50%,
+ rgba(255, 161, 22, 0.6) 75%,
+ transparent 100%);
}
.header-content {
max-width: 1200px;
margin: 0 auto;
- padding: 0 1rem;
+ padding: 0 2rem;
display: flex;
align-items: center;
justify-content: center;
+ position: relative;
+ z-index: 2;
+}
+
+.header-link {
+ text-decoration: none;
+ color: inherit;
+ cursor: pointer;
+ transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ position: relative;
+ padding: 0.5rem 1rem;
+ border-radius: 12px;
+}
+
+.header-link::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: linear-gradient(135deg, rgba(255, 161, 22, 0.1), rgba(0, 102, 204, 0.1));
+ border-radius: 12px;
+ opacity: 0;
+ transition: opacity 0.3s ease;
+}
+
+.header-link:hover {
+ transform: translateY(-2px);
+ text-shadow: 0 4px 12px rgba(255, 255, 255, 0.3);
+}
+
+.header-link:hover::before {
+ opacity: 1;
+}
+
+.header-link:active {
+ transform: translateY(0);
}
.header h1 {
margin: 0;
+ font-size: 2rem;
+ font-weight: 700;
+ background: linear-gradient(135deg, #ffffff 0%, #ffa116 50%, #0099ff 100%);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+ text-align: center;
+ line-height: 1.2;
+ letter-spacing: -0.5px;
+ position: relative;
+ padding: 0.5rem 0;
+}
+
+.header h1::after {
+ content: '🔍';
+ position: absolute;
+ top: 50%;
+ right: -2rem;
+ transform: translateY(-50%);
font-size: 1.5rem;
- font-weight: 600;
+ opacity: 0.8;
+ animation: float 3s ease-in-out infinite;
+}
+
+/* Code-inspired decoration */
+.header-content::before {
+ content: '{ }';
+ position: absolute;
+ left: 2rem;
+ top: 50%;
+ transform: translateY(-50%);
+ font-size: 1.2rem;
+ color: rgba(255, 161, 22, 0.6);
+ font-family: 'Courier New', monospace;
+ font-weight: bold;
+ opacity: 0.7;
+}
+
+.header-content::after {
+ content: '>';
+ position: absolute;
+ right: 2rem;
+ top: 50%;
+ transform: translateY(-50%);
+ font-size: 1.2rem;
+ color: rgba(0, 102, 204, 0.6);
+ font-family: 'Courier New', monospace;
+ font-weight: bold;
+ opacity: 0.7;
+}
+
+/* Floating animation */
+@keyframes float {
+ 0%, 100% {
+ transform: translateY(-50%) rotate(0deg);
+ }
+ 50% {
+ transform: translateY(-50%) rotate(10deg);
+ }
+}
+
+/* Glow effect on hover */
+@keyframes textGlow {
+ 0%, 100% {
+ text-shadow: 0 0 20px rgba(255, 255, 255, 0.3);
+ }
+ 50% {
+ text-shadow: 0 0 30px rgba(255, 161, 22, 0.5), 0 0 40px rgba(0, 102, 204, 0.3);
+ }
+}
+
+.header-link:hover h1 {
+ animation: textGlow 2s ease-in-out infinite;
+}
+
+/* Responsive Design */
+@media (max-width: 768px) {
+ .header {
+ padding: 1rem 0;
+ }
+
+ .header-content {
+ padding: 0 1rem;
+ }
+
+ .header h1 {
+ font-size: 1.5rem;
+ }
+
+ .header h1::after {
+ right: -1.5rem;
+ font-size: 1.2rem;
+ }
+
+ .header-content::before,
+ .header-content::after {
+ display: none; /* Hide code symbols on mobile */
+ }
+}
+
+@media (max-width: 480px) {
+ .header h1 {
+ font-size: 1.25rem;
+ letter-spacing: -0.25px;
+ }
+
+ .header h1::after {
+ display: none; /* Hide emoji on very small screens */
+ }
+
+ .header-link {
+ padding: 0.25rem 0.5rem;
+ }
+}
+
+/* Reduced motion support */
+@media (prefers-reduced-motion: reduce) {
+ .header-link {
+ transition: none;
+ }
+
+ .header-link:hover {
+ transform: none;
+ }
+
+ .header h1::after {
+ animation: none;
+ }
+
+ .header-link:hover h1 {
+ animation: none;
+ }
+}
+
+/* Dark theme optimization */
+@media (prefers-color-scheme: dark) {
+ .header {
+ background: linear-gradient(135deg, #0a0a0a 0%, #1a0f4d 50%, #0a0a0a 100%);
+ }
}
\ No newline at end of file
diff --git a/src/client/src/styles/layout/Pagination.css b/src/client/src/styles/layout/Pagination.css
new file mode 100644
index 0000000..a29519d
--- /dev/null
+++ b/src/client/src/styles/layout/Pagination.css
@@ -0,0 +1,94 @@
+/* styles/components/Pagination.css */
+.pagination {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 0.5rem;
+ margin: 2rem 0;
+ padding: 1rem;
+}
+
+.pagination-pages {
+ display: flex;
+ gap: 0.25rem;
+}
+
+.pagination-btn {
+ padding: 0.5rem 0.75rem;
+ border: 1px solid #e2e8f0;
+ background: white;
+ color: #4a5568;
+ border-radius: 6px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ font-weight: 500;
+ min-width: 2.5rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.pagination-btn:hover:not(:disabled) {
+ background: #f7fafc;
+ border-color: #cbd5e0;
+ transform: translateY(-1px);
+}
+
+.pagination-btn.active {
+ background: #0066cc;
+ color: white;
+ border-color: #0066cc;
+}
+
+.pagination-btn:disabled {
+ opacity: 0.4;
+ cursor: not-allowed;
+ transform: none;
+}
+
+/* Specific styles for navigation buttons */
+.pagination-first,
+.pagination-last {
+ font-weight: bold;
+ font-size: 1.1rem;
+}
+
+.pagination-prev,
+.pagination-next {
+ font-weight: bold;
+}
+
+.pagination-info {
+ text-align: center;
+ color: #666;
+ margin-bottom: 1rem;
+ font-size: 0.9rem;
+}
+
+/* Responsive */
+@media (max-width: 768px) {
+ .pagination {
+ gap: 0.25rem;
+ }
+
+ .pagination-btn {
+ padding: 0.4rem 0.6rem;
+ font-size: 0.9rem;
+ min-width: 2.25rem;
+ }
+
+ .pagination-pages {
+ gap: 0.125rem;
+ }
+
+ /* Hide page numbers on very small screens, keep only navigation */
+ @media (max-width: 480px) {
+ .pagination-pages {
+ display: none;
+ }
+
+ .pagination {
+ gap: 0.5rem;
+ }
+ }
+}
\ No newline at end of file