done homepage

This commit is contained in:
Lheorvine 2025-05-24 16:47:32 +02:00
parent 154dabfee1
commit bdad6fdedd
15 changed files with 606 additions and 94 deletions

1
Cargo.lock generated
View file

@ -1414,6 +1414,7 @@ dependencies = [
"dotenv", "dotenv",
"env_logger", "env_logger",
"log", "log",
"regex",
"rust_decimal", "rust_decimal",
"serde", "serde",
"serde_json", "serde_json",

View file

@ -17,3 +17,4 @@ log = "0.4"
bcrypt = "0.15" bcrypt = "0.15"
rust_decimal = { version = "1.37.1", features = ["serde", "db-postgres"] } rust_decimal = { version = "1.37.1", features = ["serde", "db-postgres"] }
bigdecimal = { version = "0.3.0", features = ["serde"] } bigdecimal = { version = "0.3.0", features = ["serde"] }
regex = "1.10.4"

View file

@ -0,0 +1 @@
-- Add migration script here

View file

@ -0,0 +1,4 @@
ALTER TABLE ksiazki
ADD COLUMN opis TEXT;
-- Add migration script here

View file

@ -1,2 +0,0 @@
ALTER TABLE ksiazki
ALTER COLUMN cena TYPE NUMERIC(10,2);

View file

@ -11,6 +11,8 @@ use sqlx::postgres::PgPoolOptions;
use rust_decimal::Decimal; use rust_decimal::Decimal;
use bigdecimal::BigDecimal; use bigdecimal::BigDecimal;
use serde_json::json; use serde_json::json;
use std::collections::HashMap;
use std::convert::From;
#[derive(sqlx::FromRow, serde::Serialize)] #[derive(sqlx::FromRow, serde::Serialize)]
struct Book { struct Book {
@ -18,26 +20,107 @@ struct Book {
tytul: String, tytul: String,
autor: String, autor: String,
cena: BigDecimal, cena: BigDecimal,
obraz_url: Option<String> obraz_url: Option<String>,
opis: Option<String>,
} }
#[get("/api/ksiazki")] #[get("/api/ksiazki")]
async fn get_ksiazki(pool: web::Data<sqlx::PgPool>) -> impl Responder { async fn get_ksiazki(
match sqlx::query_as!( pool: web::Data<sqlx::PgPool>,
Book, web::Query(params): web::Query<HashMap<String, String>>,
r#"SELECT id, tytul, autor, cena, obraz_url FROM ksiazki"# ) -> impl Responder {
) let search_term = params.get("search").map(|s| s.as_str()).unwrap_or("");
.fetch_all(pool.get_ref()) let sort_by = params.get("sort").map(|s| s.as_str()).unwrap_or("default");
.await
{ let base_query = "SELECT
id,
tytul,
autor,
cena,
COALESCE('/images/' || obraz_url, '/images/placeholder.jpg') as obraz_url,
COALESCE(opis, 'Brak opisu') as opis
FROM ksiazki";
let sort_clause = match sort_by {
"price_asc" => " ORDER BY cena ASC",
"price_desc" => " ORDER BY cena DESC",
"title_asc" => " ORDER BY tytul ASC",
"author_asc" => " ORDER BY autor ASC",
_ => ""
};
let query = if !search_term.is_empty() {
format!(
"{} WHERE LOWER(tytul) LIKE LOWER($1) OR LOWER(autor) LIKE LOWER($1){}",
base_query, sort_clause
)
} else {
format!("{}{}", base_query, sort_clause)
};
let mut query_builder = sqlx::query_as::<_, Book>(&query);
if !search_term.is_empty() {
query_builder = query_builder.bind(format!("%{}%", search_term));
}
match query_builder.fetch_all(pool.get_ref()).await {
Ok(books) => HttpResponse::Ok().json(books), Ok(books) => HttpResponse::Ok().json(books),
Err(e) => { Err(e) => {
log::error!("Błąd bazy danych: {:?}", e); log::error!("Błąd bazy danych: {:?}", e);
HttpResponse::InternalServerError().body(format!("Błąd: {}", e)) HttpResponse::InternalServerError().json(json!({"error": "Błąd serwera"}))
} }
} }
} }
//#[get("/api/ksiazki")]
//async fn get_ksiazki(pool: web::Data<sqlx::PgPool>) -> impl Responder {
// match sqlx::query_as!(
// Book,
// r#"SELECT id, tytul, autor, cena, obraz_url FROM ksiazki"#
// )
// .fetch_all(pool.get_ref())
// .await
// {
// Ok(books) => HttpResponse::Ok().json(books),
// Err(e) => {
// log::error!("Błąd bazy danych: {:?}", e);
// HttpResponse::InternalServerError().body(format!("Błąd: {}", e))
// }
// }
//}
#[get("/api/ksiazki/{id}")]
async fn get_ksiazka(
pool: web::Data<sqlx::PgPool>,
path: web::Path<i32>,
) -> impl Responder {
let id = path.into_inner();
match sqlx::query_as!(
Book,
r#"
SELECT
id,
tytul,
autor,
cena,
COALESCE('/images/' || obraz_url, '/images/placeholder.jpg') as obraz_url,
opis
FROM ksiazki
WHERE id = $1
"#,
id
)
.fetch_optional(pool.get_ref())
.await
{
Ok(Some(book)) => HttpResponse::Ok().json(book),
Ok(None) => HttpResponse::NotFound().finish(),
Err(e) => HttpResponse::InternalServerError().body(format!("Błąd: {}", e)),
}
}
#[get("/api/check-auth")] #[get("/api/check-auth")]
async fn check_auth() -> impl Responder { async fn check_auth() -> impl Responder {
HttpResponse::Ok().json(json!({ HttpResponse::Ok().json(json!({
@ -81,6 +164,10 @@ async fn main() -> std::io::Result<()> {
.service(get_ksiazki) .service(get_ksiazki)
.service(auth::rejestracja) .service(auth::rejestracja)
.service(auth::login) .service(auth::login)
.service(
Files::new("/images", "./static/images") // Nowy endpoint dla obrazków
.show_files_listing(),
)
.service(Files::new("/", "./static").index_file("index.html")) .service(Files::new("/", "./static").index_file("index.html"))
}) })
.bind("0.0.0.0:7999")? .bind("0.0.0.0:7999")?

83
static/book.html Normal file
View file

@ -0,0 +1,83 @@
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Dark Athenaeum</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="/css/styles.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Lobster&family=Inter:wght@400;500;700&display=swap" rel="stylesheet">
</head>
<body class="dark-theme">
<nav class="navbar navbar-expand-lg navbar-dark bg-black">
<div class="container">
<a class="navbar-brand" href="/">DARK ATHENAEUM</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse justify-content-end" id="navbarNav">
<div class="navbar-nav gap-3">
<!-- Dodaj pole wyszukiwania -->
<form class="d-flex" id="searchForm">
<input class="form-control me-2 dark-input" type="search" placeholder="Szukaj książek..." aria-label="Search">
</form>
<!-- Linki -->
<div class="anonymous-links d-flex gap-3">
<a class="nav-link" href="/login.html">Logowanie</a>
<a class="nav-link" href="/register.html">Rejestracja</a>
</div>
<div class="user-links d-flex gap-3" style="display: none;">
<a class="nav-link" href="/profile.html">Profil</a>
<a class="nav-link" href="#" id="logoutLink">Wyloguj</a>
</div>
<a class="nav-link" href="/cart.html">
<i class="bi bi-basket"></i> Koszyk
</a>
</div>
</div>
</div>
</nav>
<main class="container py-5">
<div class="row" id="book-details">
<div class="col-md-4">
<img id="book-cover" class="img-fluid mb-4" alt="Okładka książki">
</div>
<div class="col-md-8">
<h1 id="book-title" class="lobster-font neon-title mb-4"></h1>
<h3 id="book-author" class="inter-font text-accent mb-3"></h3>
<p id="book-price" class="inter-font fs-4 mb-4"></p>
<div class="card dark-card mb-4">
<div class="card-body">
<h4 class="lobster-font mb-3">Opis</h4>
<p id="book-description" class="inter-font"></p>
</div>
</div>
<button class="btn btn-gothic btn-lg">Dodaj do koszyka</button>
</div>
</div>
</main>
<footer class="mt-5">
<div class="container py-4">
<div class="row">
<div class="col-md-4">
<h5 class="lobster-font"><a href="https://sykorax.eu/">O Nas</a></h5>
</div>
<div class="col-md-4">
<h5 class="lobster-font"><a href="https://sykorax.eu/">Kontakt</a></h5>
</div>
<div class="col-md-4">
<h5 class="lobster-font"><a href="https://sykorax.eu/">Współpraca</a></h5>
</div>
</div>
</div>
</footer>
<script src="/js/book.js"></script>
</body>
</html>

View file

@ -64,3 +64,132 @@ footer {
font-size: 2.5rem; font-size: 2.5rem;
margin-bottom: 2rem; margin-bottom: 2rem;
} }
#books-container {
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}
.book-card {
max-width: none;
width: 100%;
}
.book-cover {
height: 360px;
}
.book-cover img {
object-fit: contain;
padding: 15px;
}
.book-overlay {
background: linear-gradient(0deg, rgba(7,44,36,0.9) 0%, rgba(7,44,36,0.7) 100%);
padding: 20px;
}
.book-title {
font-size: 1.2rem;
line-height: 1.4;
}
.book-cover:hover .book-overlay {
opacity: 1;
}
.book-info {
color: var(--text-gold);
text-align: center;
padding: 1rem;
}
/* Dodaj do istniejących styli */
.lobster-font {
font-family: 'Lobster', cursive;
}
.inter-font {
font-family: 'Inter', sans-serif;
}
footer a {
color: var(--accent-blue) !important;
text-decoration: none;
}
footer a:hover {
text-decoration: underline;
}
.text-accent {
color: var(--accent-blue) !important;
}
.dark-card {
background: #09342b;
border: 1px solid #1c4d42;
transition: transform 0.3s ease;
}
.dark-card:hover {
transform: translateY(-5px);
}
.text-accent {
color: #78DBFF;
}
#book-description {
line-height: 1.8;
font-size: 1.1rem;
}
#searchInput {
height: 50px;
font-size: 1.2rem;
}
/* W pliku styles.css */
.navbar-nav {
gap: 1.5rem !important; /* Odstępy między linkami */
}
footer a {
padding: 0.5rem 1rem; /* Większy obszar klikalny */
display: inline-block; /* Lepsze wyrównanie */
}
.card-img-top {
height: 350px;
object-fit: cover;
object-position: center top;
}
.bg-dark {
background-color: #072C24 !important;
}
.text-gold {
color: #E3CB9A;
text-decoration: none;
font-family: 'Inter', sans-serif;
font-weight: 500;
transition: opacity 0.3s ease;
}
.text-gold:hover {
color: #E3CB9A;
opacity: 0.8;
}
#searchInput {
min-width: 300px;
background-color: #1a322d;
color: #E3CB9A;
border: 1px solid #3d5a53;
}
#searchInput::placeholder {
color: #93B8B1;
opacity: 0.7;
}

View file

@ -5,28 +5,45 @@
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>Dark Athenaeum</title> <title>Dark Athenaeum</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css" rel="stylesheet">
<link href="/css/styles.css" rel="stylesheet"> <link href="/css/styles.css" rel="stylesheet">
<link href="https://fonts.cdnfonts.com/css/old-english-text-mt" rel="stylesheet"> <link href="https://fonts.cdnfonts.com/css/old-english-text-mt" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Lobster&family=Inter:wght@400;500;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Lobster&family=Inter:wght@400;500;700&display=swap" rel="stylesheet">
</head> </head>
<body class="dark-theme"> <body class="dark-theme">
<nav class="navbar navbar-expand-lg navbar-dark bg-black"> <nav class="navbar navbar-expand-lg navbar-dark bg-black">
<div class="navbar-nav"> <div class="container">
<!-- Dla niezalogowanych --> <a class="navbar-brand" href="/">DARK ATHENAEUM</a>
<div class="anonymous-links">
<a class="nav-link" href="/login.html">Logowanie</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<a class="nav-link" href="/register.html">Rejestracja</a> <span class="navbar-toggler-icon"></span>
</div> </button>
<!-- Dla zalogowanych --> <div class="collapse navbar-collapse justify-content-end" id="navbarNav">
<div class="user-links" style="display: none;"> <div class="navbar-nav gap-3">
<a class="nav-link" href="/profile.html">Profil</a> <form class="d-flex" id="searchForm">
<a class="nav-link" href="#" id="logoutLink">Wyloguj</a> <input class="form-control me-2 dark-input"
</div> type="search"
placeholder="Szukaj książek..."
<a class="nav-link" href="/cart.html"> aria-label="Search"
<i class="bi bi-basket"></i> Koszyk id="searchInput">
</a> </form>
<div class="anonymous-links d-flex gap-3">
<a class="nav-link" href="/login.html">Logowanie</a>
<a class="nav-link" href="/register.html">Rejestracja</a>
</div>
<div class="user-links d-flex gap-3" style="display: none !important;">
<a class="nav-link" href="/profile.html">Profil</a>
<a class="nav-link" href="#" id="logoutLink">Wyloguj</a>
</div>
<a class="nav-link" href="/cart.html">
<i class="bi bi-basket"></i> Koszyk
</a>
</div>
</div>
</div> </div>
</nav> </nav>
@ -43,6 +60,22 @@
</div> </div>
</main> </main>
<footer class="mt-5 py-3 bg-dark">
<div class="container">
<div class="row justify-content-center align-items-center text-center">
<div class="col-auto mb-2 mb-md-0">
<a href="https://sykorax.eu/" class="text-gold">O Nas</a>
</div>
<div class="col-auto">
<a href="https://sykorax.eu/" class="text-gold">Kontakt</a>
</div>
<div class="col-auto">
<a href="https://sykorax.eu/" class="text-gold">Współpraca</a>
</div>
</div>
</div>
</footer>
<script src="/js/main.js"></script> <script src="/js/main.js"></script>
</body> </body>
</html> </html>

25
static/js/book.js Normal file
View file

@ -0,0 +1,25 @@
document.addEventListener('DOMContentLoaded', async () => {
const urlParams = new URLSearchParams(window.location.search);
const bookId = urlParams.get('id');
try {
const response = await fetch(`/api/ksiazki/${bookId}`);
if (!response.ok) throw new Error('Książka nie znaleziona');
const book = await response.json();
document.getElementById('book-title').textContent = book.tytul;
document.getElementById('book-author').textContent = `Autor: ${book.autor}`;
document.getElementById('book-price').textContent = `Cena: ${book.cena} PLN`;
document.getElementById('book-description').textContent = book.opis || 'Brak opisu';
document.getElementById('book-cover').src = book.obraz_url || 'https://via.placeholder.com/400x600';
} catch (error) {
console.error('Błąd:', error);
document.getElementById('book-details').innerHTML = `
<div class="col-12 text-center">
<h2 class="text-danger">Książka nie znaleziona</h2>
<a href="/" class="btn btn-gothic mt-3">Powrót do strony głównej</a>
</div>
`;
}
});

View file

@ -1,9 +1,19 @@
document.addEventListener('DOMContentLoaded', () => {
updateNavVisibility();
setInterval(updateNavVisibility, 1000); // Aktualizuj co sekundę
});
function updateNavVisibility() { function updateNavVisibility() {
const token = localStorage.getItem('token'); const token = localStorage.getItem('token');
document.querySelectorAll('.anonymous-links, .user-links').forEach(el => { document.querySelectorAll('.anonymous-links, .user-links').forEach(el => {
el.style.display = token ? 'none' : 'block'; el.style.display = 'none';
}); });
document.querySelector('.user-links').style.display = token ? 'block' : 'none';
if (token) {
document.querySelector('.user-links').style.display = 'flex';
} else {
document.querySelector('.anonymous-links').style.display = 'flex';
}
} }
document.getElementById('logoutLink')?.addEventListener('click', (e) => { document.getElementById('logoutLink')?.addEventListener('click', (e) => {
@ -82,54 +92,77 @@ document.getElementById('registerForm')?.addEventListener('submit', async (e) =>
} }
}); });
async function loadBooks() { async function loadBooks(searchTerm = '') {
try { try {
const response = await fetch('/api/ksiazki'); const response = await fetch(`/api/ksiazki?search=${encodeURIComponent(searchTerm)}`);
if (!response.ok) { if (!response.ok) throw new Error(`Błąd HTTP: ${response.status}`);
throw new Error('Network response was not ok');
}
const books = await response.json(); const books = await response.json();
const booksContainer = document.getElementById('books-container'); renderBooks(books);
booksContainer.innerHTML = '';
books.forEach(book => {
const bookElement = document.createElement('div');
bookElement.className = 'col-md-4';
bookElement.innerHTML = `
<div class="card mb-4">
<img src="${book.obraz_url || 'https://via.placeholder.com/150'}" class="card-img-top" alt="${book.tytul}">
<div class="card-body">
<h5 class="card-title">${book.tytul}</h5>
<p class="card-text">${book.autor}</p>
<p class="card-text">${book.cena} PLN</p>
<button class="btn btn-primary">Dodaj do koszyka</button>
</div>
</div>
`;
booksContainer.appendChild(bookElement);
});
} catch (error) { } catch (error) {
console.error('Error loading books:', error); console.error('Błąd ładowania książek:', error);
const booksContainer = document.getElementById('books-container'); showError('Wystąpił błąd podczas ładowania książek');
booksContainer.innerHTML = '<div class="col-12 text-center"><p>Wystąpił błąd podczas ładowania książek.</p></div>';
} }
} }
// Inicjalizacja przy pierwszym załadowaniu
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
if (document.getElementById('books-container')) { if (document.getElementById('books-container')) {
loadBooks(); loadBooks();
} }
// Nasłuchiwanie wyszukiwania
document.getElementById('searchInput')?.addEventListener('input', (e) => {
loadBooks(e.target.value);
});
updateNavVisibility();
}); });
document.addEventListener('DOMContentLoaded', () => { document.getElementById('searchForm')?.addEventListener('submit', async (e) => {
if (document.getElementById('books-container')) { e.preventDefault();
loadBooks(); const searchTerm = document.querySelector('#searchForm input').value;
} const response = await fetch(`/api/ksiazki?search=${encodeURIComponent(searchTerm)}`);
const books = await response.json();
renderBooks(books);
}); });
document.addEventListener('DOMContentLoaded', () => { function renderBooks(books) {
if (document.getElementById('books-container')) { const container = document.getElementById('books-container');
loadBooks(); if (!container) return;
}
}); container.innerHTML = books.map(book => `
<div class="col-md-4 mb-4">
<div class="book-card card h-100">
<a href="/book.html?id=${book.id}" class="book-link">
<div class="book-cover">
<img src="${book.obraz_url}"
class="card-img-top"
alt="${book.tytul}"
onerror="this.src='/images/placeholder.jpg'">
<div class="book-overlay">
<h5 class="book-title">${book.tytul}</h5>
</div>
</div>
</a>
</div>
</div>
`).join('');
}
function showError(message) {
const container = document.getElementById('books-container');
if (!container) return;
container.innerHTML = `
<div class="col-12 text-center py-5">
<div class="alert alert-danger">
${message}<br>
<button class="btn btn-gothic mt-3" onclick="location.reload()">
Spróbuj ponownie
</button>
</div>
</div>
`;
}
document.addEventListener('DOMContentLoaded', updateNavVisibility);

39
static/js/search.js Normal file
View file

@ -0,0 +1,39 @@
document.getElementById('searchForm').addEventListener('submit', async (e) => {
e.preventDefault();
const searchTerm = document.getElementById('searchInput').value;
await loadResults(searchTerm);
});
async function loadResults(searchTerm) {
const searchTerm = document.getElementById('searchInput').value;
const sortBy = document.getElementById('sortSelect').value;
try {
const response = await fetch(`/api/ksiazki?search=${encodeURIComponent(searchTerm)}&sort=${sortBy}`);
const books = await response.json();
renderResults(books);
} catch (error) {
console.error('Błąd wyszukiwania:', error);
}
}
['input', 'change'].forEach(event => {
document.getElementById('searchInput').addEventListener(event, loadBooks);
document.getElementById('sortSelect').addEventListener(event, loadBooks);
});
function renderResults(books) {
const container = document.getElementById('search-results');
container.innerHTML = books.map(book => `
<div class="col-md-4">
<div class="card dark-card h-100">
<img src="${book.obraz_url}" class="card-img-top" alt="${book.tytul}">
<div class="card-body">
<h5 class="card-title lobster-font">${book.tytul}</h5>
<p class="card-text inter-font">${book.autor}</p>
<a href="/book.html?id=${book.id}" class="btn btn-gothic">Szczegóły</a>
</div>
</div>
</div>
`).join('');
}

View file

@ -4,28 +4,43 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Logowanie</title> <title>Logowanie</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css" rel="stylesheet">
<link href="/css/styles.css" rel="stylesheet"> <link href="/css/styles.css" rel="stylesheet">
<link href="https://fonts.cdnfonts.com/css/old-english-text-mt" rel="stylesheet"> <link href="https://fonts.cdnfonts.com/css/old-english-text-mt" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Lobster&family=Inter:wght@400;500;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Lobster&family=Inter:wght@400;500;700&display=swap" rel="stylesheet">
</head> </head>
<body class="dark-theme"> <body class="dark-theme">
<nav class="navbar navbar-expand-lg navbar-dark bg-black"> <nav class="navbar navbar-expand-lg navbar-dark bg-black">
<div class="navbar-nav"> <div class="container">
<!-- Dla niezalogowanych --> <a class="navbar-brand" href="/">DARK ATHENAEUM</a>
<div class="anonymous-links">
<a class="nav-link" href="/login.html">Logowanie</a>
<a class="nav-link" href="/register.html">Rejestracja</a>
</div>
<!-- Dla zalogowanych --> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<div class="user-links" style="display: none;"> <span class="navbar-toggler-icon"></span>
<a class="nav-link" href="/profile.html">Profil</a> </button>
<a class="nav-link" href="#" id="logoutLink">Wyloguj</a>
</div>
<a class="nav-link" href="/cart.html"> <div class="collapse navbar-collapse justify-content-end" id="navbarNav">
<i class="bi bi-basket"></i> Koszyk <div class="navbar-nav gap-3">
</a> <!-- Dodaj pole wyszukiwania -->
<form class="d-flex" id="searchForm">
<input class="form-control me-2 dark-input" type="search" placeholder="Szukaj książek..." aria-label="Search">
</form>
<!-- Linki -->
<div class="anonymous-links d-flex gap-3">
<a class="nav-link" href="/login.html">Logowanie</a>
<a class="nav-link" href="/register.html">Rejestracja</a>
</div>
<div class="user-links d-flex gap-3" style="display: none;">
<a class="nav-link" href="/profile.html">Profil</a>
<a class="nav-link" href="#" id="logoutLink">Wyloguj</a>
</div>
<a class="nav-link" href="/cart.html">
<i class="bi bi-basket"></i> Koszyk
</a>
</div>
</div>
</div> </div>
</nav> </nav>
@ -47,6 +62,22 @@
</div> </div>
</div> </div>
<footer class="mt-5 py-3 bg-dark">
<div class="container">
<div class="row justify-content-center gap-3 gap-md-0">
<div class="col-auto">
<a href="https://sykorax.eu/" class="text-gold">O Nas</a>
</div>
<div class="col-auto">
<a href="https://sykorax.eu/" class="text-gold">Kontakt</a>
</div>
<div class="col-auto">
<a href="https://sykorax.eu/" class="text-gold">Współpraca</a>
</div>
</div>
</div>
</footer>
<script src="/js/main.js"></script> <script src="/js/main.js"></script>
</body> </body>
</html> </html>

View file

@ -4,27 +4,42 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Rejestracja</title> <title>Rejestracja</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css" rel="stylesheet">
<link href="/css/styles.css" rel="stylesheet"> <link href="/css/styles.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Lobster&family=Inter:wght@400;500;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Lobster&family=Inter:wght@400;500;700&display=swap" rel="stylesheet">
</head> </head>
<body class="dark-theme"> <body class="dark-theme">
<nav class="navbar navbar-expand-lg navbar-dark bg-black"> <nav class="navbar navbar-expand-lg navbar-dark bg-black">
<div class="navbar-nav"> <div class="container">
<!-- Dla niezalogowanych --> <a class="navbar-brand" href="/">DARK ATHENAEUM</a>
<div class="anonymous-links">
<a class="nav-link" href="/login.html">Logowanie</a>
<a class="nav-link" href="/register.html">Rejestracja</a>
</div>
<!-- Dla zalogowanych --> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<div class="user-links" style="display: none;"> <span class="navbar-toggler-icon"></span>
<a class="nav-link" href="/profile.html">Profil</a> </button>
<a class="nav-link" href="#" id="logoutLink">Wyloguj</a>
</div>
<a class="nav-link" href="/cart.html"> <div class="collapse navbar-collapse justify-content-end" id="navbarNav">
<i class="bi bi-basket"></i> Koszyk <div class="navbar-nav gap-3">
</a> <!-- Dodaj pole wyszukiwania -->
<form class="d-flex" id="searchForm">
<input class="form-control me-2 dark-input" type="search" placeholder="Szukaj książek..." aria-label="Search">
</form>
<!-- Linki -->
<div class="anonymous-links d-flex gap-3">
<a class="nav-link" href="/login.html">Logowanie</a>
<a class="nav-link" href="/register.html">Rejestracja</a>
</div>
<div class="user-links d-flex gap-3" style="display: none;">
<a class="nav-link" href="/profile.html">Profil</a>
<a class="nav-link" href="#" id="logoutLink">Wyloguj</a>
</div>
<a class="nav-link" href="/cart.html">
<i class="bi bi-basket"></i> Koszyk
</a>
</div>
</div>
</div> </div>
</nav> </nav>
@ -51,6 +66,22 @@
</form> </form>
</div> </div>
<footer class="mt-5 py-3 bg-dark">
<div class="container">
<div class="row justify-content-center gap-3 gap-md-0">
<div class="col-auto">
<a href="https://sykorax.eu/" class="text-gold">O Nas</a>
</div>
<div class="col-auto">
<a href="https://sykorax.eu/" class="text-gold">Kontakt</a>
</div>
<div class="col-auto">
<a href="https://sykorax.eu/" class="text-gold">Współpraca</a>
</div>
</div>
</div>
</footer>
<script src="/js/main.js"></script> <script src="/js/main.js"></script>
</body> </body>
</html> </html>

16
static/search.html Normal file
View file

@ -0,0 +1,16 @@
<div class="container">
<div class="row mb-4">
<div class="col-md-6">
<input type="text" class="form-control dark-input" id="searchInput" placeholder="Szukaj...">
</div>
<div class="col-md-6">
<select class="form-select dark-input" id="sortSelect">
<option value="default">Domyślnie</option>
<option value="price_asc">Cena rosnąco</option>
<option value="price_desc">Cena malejąco</option>
<option value="title_asc">Tytuł A-Z</option>
<option value="author_asc">Autor A-Z</option>
</select>
</div>
</div>
</div>