From 1f414d0a7052e803a51bef21bd7af366e8ee6089 Mon Sep 17 00:00:00 2001 From: Lheorvine Date: Sun, 25 May 2025 16:54:16 +0200 Subject: [PATCH] history-init --- src/main.rs | 36 ++++++++++++++++++--------------- static/cart.html | 5 +++++ static/css/styles.css | 12 +++++++++++ static/js/cart.js | 44 ++++++++++++++++++++++++++++++++++++++++ static/js/profile.js | 47 +++++++++++++++++++++++++------------------ static/thankyou.html | 17 ++++++++++++++++ 6 files changed, 125 insertions(+), 36 deletions(-) create mode 100644 static/thankyou.html diff --git a/src/main.rs b/src/main.rs index 82d03f2..31f118a 100644 --- a/src/main.rs +++ b/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, data: web::Json, ) -> Result { - 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] diff --git a/static/cart.html b/static/cart.html index 69070c1..f71fcfd 100644 --- a/static/cart.html +++ b/static/cart.html @@ -15,6 +15,11 @@

Twój koszyk

+
+ +
diff --git a/static/css/styles.css b/static/css/styles.css index 9a66f6a..9e6e50f 100644 --- a/static/css/styles.css +++ b/static/css/styles.css @@ -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); diff --git a/static/js/cart.js b/static/js/cart.js index 3863aa1..432eecc 100644 --- a/static/js/cart.js +++ b/static/js/cart.js @@ -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); + } +}); diff --git a/static/js/profile.js b/static/js/profile.js index 5332f88..bf0fc2f 100644 --- a/static/js/profile.js +++ b/static/js/profile.js @@ -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 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 => ` -
-
-
Zamówienie #${order.id}
-

Data: ${new Date(order.data_zamowienia).toLocaleDateString()}

-

Status: ${order.status}

-

Suma: ${order.suma_totalna} PLN

+ container.innerHTML = ''; + + orders.forEach(order => { + const orderDate = new Date(order.data_zamowienia).toLocaleDateString(); + const orderHTML = ` +
+
+
Zamówienie #${order.id}
+

Data: ${orderDate}

+

Suma: ${order.suma_totalna} PLN

+

Status: ${order.status || 'Przyjęto do realizacji'}

+
-
- `).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); +}); diff --git a/static/thankyou.html b/static/thankyou.html new file mode 100644 index 0000000..4b0aa5b --- /dev/null +++ b/static/thankyou.html @@ -0,0 +1,17 @@ + + + + + Podziękowanie - Dark Athenaeum + + + + +
+

Dziękujemy za zakup!

+

Twoje zamówienie zostało pomyślnie zrealizowane.

+ Zobacz historię zamówień + Strona główna +
+ +