history-init
This commit is contained in:
parent
b7f3a43495
commit
1f414d0a70
6 changed files with 125 additions and 36 deletions
36
src/main.rs
36
src/main.rs
|
@ -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]
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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 => `
|
||||
<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>
|
||||
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 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>
|
||||
</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
17
static/thankyou.html
Normal 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>
|
Loading…
Add table
Reference in a new issue