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 actix_web::http::header;
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
use bigdecimal::FromPrimitive;
|
use bigdecimal::FromPrimitive;
|
||||||
|
use std::convert::Infallible;
|
||||||
|
|
||||||
mod auth;
|
mod auth;
|
||||||
|
|
||||||
|
@ -360,30 +361,25 @@ async fn checkout(
|
||||||
pool: web::Data<sqlx::PgPool>,
|
pool: web::Data<sqlx::PgPool>,
|
||||||
data: web::Json<CheckoutRequest>,
|
data: web::Json<CheckoutRequest>,
|
||||||
) -> Result<HttpResponse, actix_web::Error> {
|
) -> Result<HttpResponse, actix_web::Error> {
|
||||||
let token = req.headers().get("Authorization")
|
let user_id = validate_token(get_token(&req)).await?;
|
||||||
.and_then(|h| h.to_str().ok());
|
|
||||||
|
|
||||||
let user_id = validate_token(token).await?;
|
let mut transaction = pool.begin().await
|
||||||
|
.map_err(|e| actix_web::error::ErrorInternalServerError(e))?;
|
||||||
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"))?;
|
|
||||||
|
|
||||||
|
// 1. Utwórz zamówienie
|
||||||
let order_id = sqlx::query!(
|
let order_id = sqlx::query!(
|
||||||
"INSERT INTO zamowienia (user_id, suma_totalna)
|
"INSERT INTO zamowienia (user_id, suma_totalna)
|
||||||
VALUES ($1, $2) RETURNING id",
|
VALUES ($1, $2) RETURNING id",
|
||||||
user_id,
|
user_id,
|
||||||
total_bigdec
|
BigDecimal::from_f64(data.total).ok_or_else(||
|
||||||
|
actix_web::error::ErrorBadRequest("Invalid total value"))?
|
||||||
)
|
)
|
||||||
.fetch_one(&mut *transaction)
|
.fetch_one(&mut *transaction)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| actix_web::error::ErrorInternalServerError(e))?
|
.map_err(|e| actix_web::error::ErrorInternalServerError(e))?
|
||||||
.id;
|
.id;
|
||||||
|
|
||||||
// Dodaj pozycje zamówienia
|
// 2. Dodaj pozycje zamówienia
|
||||||
for item in &data.items {
|
for item in &data.items {
|
||||||
let book = sqlx::query!(
|
let book = sqlx::query!(
|
||||||
"SELECT cena FROM ksiazki WHERE id = $1",
|
"SELECT cena FROM ksiazki WHERE id = $1",
|
||||||
|
@ -406,11 +402,19 @@ async fn checkout(
|
||||||
.map_err(|e| actix_web::error::ErrorInternalServerError(e))?;
|
.map_err(|e| actix_web::error::ErrorInternalServerError(e))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction.commit().await.map_err(|e| {
|
// 3. Wyczyść koszyk
|
||||||
actix_web::error::ErrorInternalServerError(e)
|
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]
|
#[actix_web::main]
|
||||||
|
|
|
@ -15,6 +15,11 @@
|
||||||
<main class="container py-5">
|
<main class="container py-5">
|
||||||
<h2 class="neon-title mb-4">Twój koszyk</h2>
|
<h2 class="neon-title mb-4">Twój koszyk</h2>
|
||||||
<div id="cart-items" class="row g-4"></div>
|
<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>
|
</main>
|
||||||
<script src="/js/cart.js"></script>
|
<script src="/js/cart.js"></script>
|
||||||
</body>
|
</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 {
|
.neon-title {
|
||||||
color: #0ff;
|
color: #0ff;
|
||||||
text-shadow: 0 0 10px rgba(0, 255, 255, 0.5);
|
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');
|
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 {
|
try {
|
||||||
const response = await fetch('/api/order-history', {
|
const token = localStorage.getItem('token');
|
||||||
headers: getAuthHeaders()
|
if (!token) {
|
||||||
});
|
|
||||||
|
|
||||||
if (response.status === 401) {
|
|
||||||
window.location.href = '/login.html';
|
window.location.href = '/login.html';
|
||||||
return;
|
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');
|
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 dark-card mb-3">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5>Zamówienie #${order.id}</h5>
|
<h5 class="card-title">Zamówienie #${order.id}</h5>
|
||||||
<p>Data: ${new Date(order.data_zamowienia).toLocaleDateString()}</p>
|
<p class="card-text">Data: ${orderDate}</p>
|
||||||
<p>Status: ${order.status}</p>
|
<p class="card-text">Suma: ${order.suma_totalna} PLN</p>
|
||||||
<p>Suma: ${order.suma_totalna} PLN</p>
|
<p class="card-text">Status: ${order.status || 'Przyjęto do realizacji'}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`).join('');
|
`;
|
||||||
|
container.insertAdjacentHTML('beforeend', orderHTML);
|
||||||
|
});
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error:', 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