Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions bookshelf-frontend/src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useState } from 'react';
import { Routes, Route } from 'react-router-dom';

Expand Down Expand Up @@ -25,6 +27,18 @@ import OrderHistory from './pages/OrderHistory.jsx';
import './App.css';

export default function App() {
const [activeGenre, setActiveGenre] = useState('All');
const [cart, setCart] = useState([]);
const navigate = useNavigate();

const visibleBooks = useMemo(() => {
if (activeGenre === 'All') return books;
return books.filter((book) => book.genre === activeGenre);
}, [activeGenre]);

function handleAddToCart(book) {
setCart((prev) => [...prev, book]);
}
const [searchQuery, setSearchQuery] = useState('');

return (
Expand All @@ -33,6 +47,7 @@ export default function App() {
<ScrollToTop />
<CustomCursor />

<Navbar cartCount={cart.length} onCartClick={() => navigate('/checkout')} />
<Navbar
searchQuery={searchQuery}
setSearchQuery={setSearchQuery}
Expand Down
107 changes: 107 additions & 0 deletions bookshelf-frontend/src/components/CheckoutGateway.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
.checkout-gateway {
display: flex;
justify-content: center;
align-items: center;
min-height: 60vh;
padding: 40px 20px;
}

.checkout-gateway__inner {
background: var(--paper-dim);
border: 1px solid var(--line);
border-radius: var(--radius-card);
padding: 40px;
max-width: 600px;
width: 100%;
text-align: center;
}

.checkout-gateway__title {
font-family: var(--font-display);
font-size: 28px;
color: var(--ink);
margin-bottom: 8px;
}

.checkout-gateway__subtitle {
color: var(--ink-soft);
margin-bottom: 32px;
}

.checkout-gateway__options {
display: flex;
flex-direction: column;
gap: 20px;
}

.checkout-gateway__option {
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
}

.checkout-gateway__option h3 {
font-family: var(--font-body);
font-size: 18px;
margin: 0;
}

.checkout-gateway__option p {
font-size: 14px;
color: var(--ink-soft);
max-width: 80%;
}

.checkout-gateway__divider {
display: flex;
align-items: center;
color: var(--ink-soft);
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
}

.checkout-gateway__divider::before,
.checkout-gateway__divider::after {
content: '';
flex: 1;
height: 1px;
background: var(--line);
margin: 0 16px;
}

.btn-primary {
background: var(--ink);
color: var(--paper);
border: none;
padding: 10px 24px;
border-radius: 6px;
font-weight: 600;
cursor: pointer;
transition: opacity 0.2s ease;
width: 100%;
max-width: 250px;
}

.btn-primary:hover {
opacity: 0.9;
}

.btn-secondary {
background: transparent;
color: var(--ink);
border: 1px solid var(--ink);
padding: 10px 24px;
border-radius: 6px;
font-weight: 600;
cursor: pointer;
transition: background 0.2s ease, color 0.2s ease;
width: 100%;
max-width: 250px;
}

.btn-secondary:hover {
background: var(--ink);
color: var(--paper);
}
51 changes: 51 additions & 0 deletions bookshelf-frontend/src/components/CheckoutGateway.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { useEffect } from 'react';
import './CheckoutGateway.css';

export default function CheckoutGateway({ onProceedToGuest, onProceedToAuth }) {
useEffect(() => {
// Automatically skip the gateway if the user is authenticated
const isAuth = localStorage.getItem('isAuthenticated');
if (isAuth) {
onProceedToAuth();
}
}, [onProceedToAuth]);

return (
<div className="checkout-gateway">
<div className="checkout-gateway__inner">
<h2 className="checkout-gateway__title">Checkout</h2>
<p className="checkout-gateway__subtitle">Choose how you would like to proceed with your order.</p>

<div className="checkout-gateway__options">
<div className="checkout-gateway__option">
<h3>Already have an account?</h3>
<p>Log in for faster checkout and to track your order history.</p>
<button className="btn-primary" onClick={() => window.location.href = '/login'}>
Log In
</button>
</div>

<div className="checkout-gateway__divider">OR</div>

<div className="checkout-gateway__option">
<h3>New here?</h3>
<p>Create an account to save your details for future purchases.</p>
<button className="btn-secondary" onClick={() => window.location.href = '/signup'}>
Create Account
</button>
</div>

<div className="checkout-gateway__divider">OR</div>

<div className="checkout-gateway__option">
<h3>Fast checkout without creating an account</h3>
<p>You can complete your purchase as a guest. No account required.</p>
<button className="btn-secondary" onClick={onProceedToGuest}>
Continue as Guest
</button>
</div>
</div>
</div>
</div>
);
}
93 changes: 93 additions & 0 deletions bookshelf-frontend/src/components/GuestCheckoutForm.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
.guest-checkout {
background: var(--paper-dim);
border: 1px solid var(--line);
border-radius: var(--radius-card);
padding: 40px;
max-width: 600px;
width: 100%;
margin: 40px auto;
}

.guest-checkout__title {
font-family: var(--font-display);
font-size: 24px;
color: var(--ink);
margin-bottom: 8px;
}

.guest-checkout__subtitle {
color: var(--ink-soft);
margin-bottom: 24px;
font-size: 14px;
}

.guest-checkout__form {
display: flex;
flex-direction: column;
gap: 20px;
}

.form-group {
display: flex;
flex-direction: column;
gap: 8px;
}

.form-row {
display: flex;
gap: 20px;
}

.form-row .form-group {
flex: 1;
}

.guest-checkout label {
font-size: 14px;
font-weight: 600;
color: var(--ink);
}

.guest-checkout input {
padding: 12px;
border: 1px solid var(--line);
border-radius: 6px;
background: var(--paper);
color: var(--ink);
font-family: var(--font-body);
font-size: 14px;
transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.guest-checkout input:focus {
outline: none;
border-color: var(--ink);
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.05);
}

.guest-checkout input.error {
border-color: #e53e3e;
}

.error-text {
color: #e53e3e;
font-size: 12px;
}

.btn-submit {
margin-top: 10px;
background: var(--ink);
color: var(--paper);
border: none;
padding: 14px;
border-radius: 6px;
font-weight: 600;
cursor: pointer;
transition: opacity 0.2s ease;
width: 100%;
font-size: 16px;
}

.btn-submit:hover {
opacity: 0.9;
}
Loading
Loading