The wishlist has its table, its API and its hook. Now a visitor needs something to click. On each product card, a logged-in visitor gets a toggle button: always the same words, Save for later, either on or off. Its aria-pressed attribute tells the browser, screen readers and the check whether it is on. The check prints (pressed) when it is. A guest has no wishlist, so a guest gets a link to log in instead.
Here is a toggle for another job, a mute button, and a guest link to another page:
<button type="button" aria-pressed={muted} onClick={() => setMuted(!muted)}>
Mute
</button>
{!user && <Link to="/login?next=/cart">Log in to see your cart</Link>}
The words inside a button are its name. Without them the check prints button: (no name) and cannot click it. type="button" keeps a button from ever submitting a form. The given ProductsPage passes each card saved (the hook's has(product.id)) and onToggle (the hook's toggle).
The check opens the shop as a guest, follows the link, logs in as Ana, then saves and unsaves. It must see:
> open the page (a guest)
item: Mug $12
link: Details -> /products/1
link: Log in to save -> /login?next=/
> log in as ana@example.com
item: Mug $12
link: Details -> /products/1
button: Add to cart
button: Save for later
> click "Save for later" in "Mug"
request: PUT /api/wishlist/1 -> 204
button: Save for later (pressed)
> click "Save for later" in "Teapot", then "Wishlist"
item: Mug $12
item: Teapot $22
> back on Products, click "Save for later" in "Mug" again
request: DELETE /api/wishlist/1 -> 204
button: Save for later
Your task: in client/src/components/ProductCard.jsx, add a Log in to save link for guests. Then finish the empty button: its text Save for later, type="button", aria-pressed={saved}, and an onClick that calls onToggle with the product's id.
Assignment
Follow the Coding Tutorial to finish the product card's wishlist part: a "Log in to save" link for guests and a "Save for later" toggle button for logged-in visitors.
Hint
The button block is already there, inside {user !== null && ( … )}. The link goes below it, inside {!user && …}. In onClick, wrap the call in an arrow function, so it runs on the click and not while the card is drawn.
Free plan: 30 tutor messages. PRO is unlimited.
