Skip to content

Commit

Permalink
Polish UI (#68)
Browse files Browse the repository at this point in the history
* Make item card cleaner

* Tweak modal close button

* Remove boilerplate CSS from `index.css`

* Merge info and bid modals

* Merge remote-tracking branch 'origin/main' into styling
  • Loading branch information
hmellor authored Mar 9, 2024
1 parent 3f5b21e commit 9a60fd8
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 195 deletions.
19 changes: 3 additions & 16 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,7 @@ html * {
}

/* Bootstrap tweaks */
.card-img-top {
width: 100%;
height: 16em;
object-fit: cover;
}

.list-group-horizontal > .list-group-item {
border: none;
}

.modal-body > img {
width: 100%;
}

.card > .table {
margin-bottom: 0;
.card:hover {
cursor: pointer;
box-shadow: 0 0 0.2rem gray;
}
41 changes: 6 additions & 35 deletions src/components/Item.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,49 +45,20 @@ export const Item = ({ item }) => {

return (
<div className="col">
<div className="card">
<div className="card h-100" onClick={() => openModal(ModalTypes.ITEM, item)}>
<img
src={primaryImageSrc}
className="card-img-top"
alt={item.title}
/>
<div className="card-body">
<h5 className="title">{item.title}</h5>
<p className="card-subtitle">{item.subtitle}</p>

<table className="table">
<tbody>
<tr>
<th scope="row">Current bid:</th>
<td className="current-bid">
{amount} [{bids} bids]
</td>
</tr>
<tr>
<th scope="row">Time left:</th>
<td className="time-left">{timeLeft}</td>
</tr>
</tbody>
</table>

<div className="btn-group">
<button
onClick={() => openModal(ModalTypes.INFO, item)}
type="button"
className="btn btn-secondary"
>
Info
</button>
<button
disabled={biddingComplete}
onClick={() => openModal(ModalTypes.BID, item)}
type="button"
className="btn btn-primary"
>
Submit bid
</button>
</div>
<h6 className="card-subtitle mb-2 text-body-secondary">{item.subtitle}</h6>
</div>
<ul className="list-group list-group-flush">
<li className="list-group-item"><strong>{amount}</strong></li>
<li className="list-group-item">{bids} bids · {timeLeft}</li>
</ul>
</div>
</div>
);
Expand Down
216 changes: 90 additions & 126 deletions src/components/Modal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,8 @@ const Modal = ({ type, title, children }) => {
>
<div className="modal-content">
<div className="modal-header">
<h2 className="modal-title">{title}</h2>
<button
type="button"
className="btn-close"
onClick={closeModal}
></button>
<h5 className="modal-title">{title}</h5>
<button className="btn-close" onClick={closeModal} />
</div>
{children}
</div>
Expand All @@ -47,9 +43,15 @@ Modal.propTypes = {
children: PropTypes.arrayOf(PropTypes.element)
}

const InfoModal = () => {
const { openModal, closeModal, activeItem } = useContext(ModalsContext);
const ItemModal = () => {
const { activeItem, openModal, closeModal } = useContext(ModalsContext);
const [secondaryImageSrc, setSecondaryImageSrc] = useState("");
const minIncrease = 1;
const [bid, setBid] = useState();
const [valid, setValid] = useState("");
const [isSubmitting, setIsSubmitting] = useState("");
const [feedback, setFeedback] = useState("");
const [minBid, setMinBid] = useState("-.--");

useEffect(() => {
if (activeItem.secondaryImage === undefined) return;
Expand All @@ -58,104 +60,6 @@ const InfoModal = () => {
})
}, [activeItem.secondaryImage])

return (
<Modal type={ModalTypes.INFO} title={activeItem.title}>
<div className="modal-body">
<p>{activeItem.detail}</p>
<img src={secondaryImageSrc} alt={activeItem.title} />
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-secondary"
onClick={closeModal}
>
Close
</button>
<button
type="button"
className="btn btn-primary"
onClick={() => openModal(ModalTypes.BID, activeItem)}
disabled={activeItem.endTime - new Date().getTime() < 0}
>
Submit bid
</button>
</div>
</Modal>
);
};

const SignUpModal = () => {
const { closeModal } = useContext(ModalsContext);
const [username, setUsername] = useState("");
const [valid, setValid] = useState("");

const handleSignUp = () => {
const user = auth.currentUser;
updateProfile(user, { displayName: username });
setDoc(doc(db, "users", user.uid), { name: username, admin: "" });
console.debug(`signUp() write to users/${user.uid}`);
setValid("is-valid");
setTimeout(() => {
closeModal();
setValid("");
}, 1000);
};

const handleKeyDown = (e) => {
if (e.key === "Enter") {
handleSignUp();
}
};

return (
<Modal type={ModalTypes.SIGN_UP} title="Sign up for Markatplace Auction">
<div className="modal-body">
<p>
We use anonymous authentication provided by Google. Your account is
attached to your device signature.
</p>
<p>The username just lets us know who&apos;s bidding!</p>
<form onSubmit={(e) => e.preventDefault()}>
<div className="form-floating mb-3">
<input
autoFocus
id="username-input"
type="username"
className={`form-control ${valid}`}
value={username}
onChange={(e) => setUsername(e.target.value)}
onKeyDown={handleKeyDown}
/>
<label>Username</label>
</div>
</form>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-secondary">
Cancel
</button>
<button
type="submit"
className="btn btn-primary"
onClick={handleSignUp}
>
Sign up
</button>
</div>
</Modal>
);
};

const BidModal = () => {
const { closeModal, activeItem } = useContext(ModalsContext);
const minIncrease = 1;
const [bid, setBid] = useState();
const [valid, setValid] = useState("");
const [isSubmitting, setIsSubmitting] = useState("");
const [feedback, setFeedback] = useState("");
const [minBid, setMinBid] = useState("-.--");

useEffect(() => {
const status = itemStatus(activeItem);
setMinBid(formatMoney(activeItem.currency, status.amount + minIncrease));
Expand All @@ -179,6 +83,18 @@ const BidModal = () => {
setFeedback("Sorry, this item has ended!");
setValid("is-invalid");
delayedClose();
setIsSubmitting(false);
return;
}
// Ensure user has provided a username
if (auth.currentUser.displayName == null) {
setFeedback("You must provide a username before bidding!");
setValid("is-invalid");
setTimeout(() => {
openModal(ModalTypes.SIGN_UP);
setIsSubmitting(false);
setValid("");
}, 1000)
return;
}
// Ensure input is a monetary value
Expand Down Expand Up @@ -223,48 +139,96 @@ const BidModal = () => {
};

return (
<Modal type={ModalTypes.BID} title={"Place your bid"}>
<Modal type={ModalTypes.ITEM} title={activeItem.title}>
<div className="modal-body">
<p>{activeItem.detail}</p>
<img src={secondaryImageSrc} className="img-fluid" alt={activeItem.title} />
</div>
<div className="modal-footer justify-content-start">
<div className="input-group mb-2">
<span className="input-group-text">{activeItem.currency}</span>
<input
className={`form-control ${valid}`}
onChange={handleChange}
onKeyDown={handleKeyDown}
/>
<button
type="submit"
className="btn btn-primary"
onClick={handleSubmitBid}
disabled={isSubmitting}
>
Submit bid
</button>
<div className="invalid-feedback">{feedback}</div>
</div>
<label className="form-label">Enter {minBid} or more</label>
<p className="text-muted">(This is just a demo, you&apos;re not bidding real money)</p>
</div>
</Modal>
);
};

const SignUpModal = () => {
const { closeModal } = useContext(ModalsContext);
const [username, setUsername] = useState("");
const [valid, setValid] = useState("");

const handleSignUp = () => {
const user = auth.currentUser;
updateProfile(user, { displayName: username });
setDoc(doc(db, "users", user.uid), { name: username, admin: "" });
console.debug(`signUp() write to users/${user.uid}`);
setValid("is-valid");
setTimeout(() => {
closeModal();
setValid("");
}, 1000);
};

const handleKeyDown = (e) => {
if (e.key === "Enter") {
handleSignUp();
}
};

return (
<Modal type={ModalTypes.SIGN_UP} title="Sign up for Markatplace Auction">
<div className="modal-body">
<p>
You are about to place a bid on <strong>{activeItem.title}</strong>
</p>
<p className="text-muted">
(This is just a demo, you&apos;re not bidding real money)
We use anonymous authentication provided by Google. Your account is
attached to your device signature.
</p>
<p>The username just lets us know who&apos;s bidding!</p>
<form onSubmit={(e) => e.preventDefault()}>
<div className="form-floating mb-3">
<input
autoFocus
id="amount-input"
type="amount"
id="username-input"
type="username"
className={`form-control ${valid}`}
onChange={handleChange}
value={username}
onChange={(e) => setUsername(e.target.value)}
onKeyDown={handleKeyDown}
/>
<label>Enter {minBid} or more</label>
<div className="invalid-feedback">{feedback}</div>
<label>Username</label>
</div>
</form>
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-secondary"
onClick={closeModal}
>
Close
<button type="button" className="btn btn-secondary">
Cancel
</button>
<button
type="submit"
className="btn btn-primary"
onClick={handleSubmitBid}
disabled={isSubmitting}
onClick={handleSignUp}
>
Submit bid
Sign up
</button>
</div>
</Modal>
);
};

export { InfoModal, SignUpModal, BidModal };
export { ItemModal, SignUpModal };
13 changes: 0 additions & 13 deletions src/index.css
Original file line number Diff line number Diff line change
@@ -1,13 +0,0 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
5 changes: 2 additions & 3 deletions src/pages/Home.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import Grid from "../components/Grid";
import { InfoModal, BidModal } from "../components/Modal";
import { ItemModal } from "../components/Modal";

function HomePage() {
return (
<div className="container mt-3">
<Grid />
<InfoModal />
<BidModal />
<ItemModal />
</div>
);
}
Expand Down
3 changes: 1 addition & 2 deletions src/utils/modalTypes.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export const ModalTypes = {
INFO: "info",
ITEM: "item",
SIGN_UP: "signUp",
BID: "bid",
NONE: null,
};

0 comments on commit 9a60fd8

Please sign in to comment.