history-init

This commit is contained in:
Lheorvine 2025-05-25 16:54:16 +02:00
parent b7f3a43495
commit 1f414d0a70
6 changed files with 125 additions and 36 deletions

View file

@ -13,6 +13,7 @@ use sqlx::FromRow;
use actix_web::http::header;
use sqlx::Row;
use bigdecimal::FromPrimitive;
use std::convert::Infallible;
mod auth;
@ -360,30 +361,25 @@ async fn checkout(
pool: web::Data<sqlx::PgPool>,
data: web::Json<CheckoutRequest>,
) -> Result<HttpResponse, actix_web::Error> {
let token = req.headers().get("Authorization")
.and_then(|h| h.to_str().ok());
let user_id = validate_token(get_token(&req)).await?;
let user_id = validate_token(token).await?;
let mut transaction = pool.begin().await.map_err(|e| {
actix_web::error::ErrorInternalServerError(e)
})?;
let total_bigdec = BigDecimal::from_f64(data.total)
.ok_or_else(|| actix_web::error::ErrorBadRequest("Invalid total value"))?;
let mut transaction = pool.begin().await
.map_err(|e| actix_web::error::ErrorInternalServerError(e))?;
// 1. Utwórz zamówienie
let order_id = sqlx::query!(
"INSERT INTO zamowienia (user_id, suma_totalna)
VALUES ($1, $2) RETURNING id",
user_id,
total_bigdec
BigDecimal::from_f64(data.total).ok_or_else(||
actix_web::error::ErrorBadRequest("Invalid total value"))?
)
.fetch_one(&mut *transaction)
.await
.map_err(|e| actix_web::error::ErrorInternalServerError(e))?
.id;
// Dodaj pozycje zamówienia
// 2. Dodaj pozycje zamówienia
for item in &data.items {
let book = sqlx::query!(
"SELECT cena FROM ksiazki WHERE id = $1",
@ -406,11 +402,19 @@ async fn checkout(
.map_err(|e| actix_web::error::ErrorInternalServerError(e))?;
}
transaction.commit().await.map_err(|e| {
actix_web::error::ErrorInternalServerError(e)
})?;
// 3. Wyczyść koszyk
sqlx::query!(
"DELETE FROM koszyk WHERE user_id = $1",
user_id
)
.execute(&mut *transaction)
.await
.map_err(|e| actix_web::error::ErrorInternalServerError(e))?;
Ok(HttpResponse::Ok().json(json!({"status": "success", "order_id": order_id})))
transaction.commit().await
.map_err(|e| actix_web::error::ErrorInternalServerError(e))?;
Ok(HttpResponse::Ok().json(json!({"status": "success"})))
}
#[actix_web::main]

View file

@ -15,6 +15,11 @@
<main class="container py-5">
<h2 class="neon-title mb-4">Twój koszyk</h2>
<div id="cart-items" class="row g-4"></div>
<div class="text-center mt-5">
<button id="checkoutBtn" class="btn btn-gothic btn-lg">
<i class="bi bi-wallet2"></i> Złóż zamówienie
</button>
</div>
</main>
<script src="/js/cart.js"></script>
</body>

View file

@ -234,6 +234,18 @@ footer a {
}
}
.btn-outline-gothic {
border: 2px solid #0ff;
color: #0ff;
transition: all 0.3s ease;
}
.btn-outline-gothic:hover {
background-color: #0ff;
color: #000;
box-shadow: 0 0 15px #0ff;
}
.neon-title {
color: #0ff;
text-shadow: 0 0 10px rgba(0, 255, 255, 0.5);

View file

@ -89,3 +89,47 @@ document.addEventListener('DOMContentLoaded', async () => {
alert('Nie udało się załadować koszyka');
}
});
document.getElementById('checkoutBtn').addEventListener('click', async () => {
try {
const token = localStorage.getItem('token');
if (!token) {
window.location.href = '/login.html';
return;
}
// Pobierz aktualną zawartość koszyka
const cartResponse = await fetch('/api/cart', {
headers: { 'Authorization': `Bearer ${token}` }
});
const cartItems = await cartResponse.json();
// Przygotuj dane do zamówienia
const checkoutData = {
items: cartItems.map(item => ({
book_id: item.book_id,
quantity: item.quantity
})),
total: cartItems.reduce((sum, item) =>
sum + (parseFloat(item.cena) * item.quantity), 0)
};
// Wyślij zamówienie
const response = await fetch('/api/checkout', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify(checkoutData)
});
if (!response.ok) throw new Error('Błąd podczas składania zamówienia');
window.location.href = '/thankyou.html';
} catch (error) {
console.error('Error:', error);
alert('Nie udało się złożyć zamówienia: ' + error.message);
}
});

View file

@ -1,31 +1,38 @@
async function loadOrderHistory() {
document.addEventListener('DOMContentLoaded', async () => {
try {
const response = await fetch('/api/order-history', {
headers: getAuthHeaders()
});
if (response.status === 401) {
const token = localStorage.getItem('token');
if (!token) {
window.location.href = '/login.html';
return;
}
const orders = await response.json();
const response = await fetch('/api/order-history', {
headers: { 'Authorization': `Bearer ${token}` }
});
if (!response.ok) throw new Error('Błąd ładowania historii');
const orders = await response.json();
const container = document.getElementById('order-history');
container.innerHTML = orders.map(order => `
container.innerHTML = '';
orders.forEach(order => {
const orderDate = new Date(order.data_zamowienia).toLocaleDateString();
const orderHTML = `
<div class="card dark-card mb-3">
<div class="card-body">
<h5>Zamówienie #${order.id}</h5>
<p>Data: ${new Date(order.data_zamowienia).toLocaleDateString()}</p>
<p>Status: ${order.status}</p>
<p>Suma: ${order.suma_totalna} PLN</p>
<h5 class="card-title">Zamówienie #${order.id}</h5>
<p class="card-text">Data: ${orderDate}</p>
<p class="card-text">Suma: ${order.suma_totalna} PLN</p>
<p class="card-text">Status: ${order.status || 'Przyjęto do realizacji'}</p>
</div>
</div>
`).join('');
`;
container.insertAdjacentHTML('beforeend', orderHTML);
});
} catch (error) {
console.error('Error:', error);
alert('Nie udało się załadować historii zamówień');
}
}
document.addEventListener('DOMContentLoaded', loadOrderHistory);
});

17
static/thankyou.html Normal file
View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Podziękowanie - 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">
</head>
<body class="dark-theme">
<main class="container py-5 text-center">
<h1 class="neon-title mb-4">Dziękujemy za zakup!</h1>
<p class="inter-font fs-5">Twoje zamówienie zostało pomyślnie zrealizowane.</p>
<a href="/profile.html" class="btn btn-gothic">Zobacz historię zamówień</a>
<a href="/" class="btn btn-outline-gothic ms-2">Strona główna</a>
</main>
</body>
</html>