Tell us what’s happening:
I am currently attempting the build a flashcard app and my app isn’t passing test 8: The delete button should remove a flashcard element from the currentCards collection. The best idea I have is because I am using localStorage to save the user’s data and load it when launched but I don’t know why that would make the test fail.
Your code so far
<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Deki Deck</title>
<link rel="stylesheet" href="styles.css" />
<link href="https://fonts.googleapis.com/css2?family=Righteous&family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
</head>
<body>
<header class="flex align-center justify-between section-width lr-padding">
<a href="#"><h1 id="logo" class="flex column align-center" aria-hidden>Deki Deck</h1></a>
<a href="#" id="user-avatar-link"><img id="user-avatar" src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fcdn.pixabay.com%2Fphoto%2F2011%2F12%2F13%2F14%2F28%2Fearth-11009_1280.jpg&f=1&nofb=1&ipt=597a537adaa5745ef46f8981728f8a0f06162c4ad557a8fd12815ac43bfbb06f" alt="User profile picture" /></a>
</header>
<main class="section-width flex align-center column center justify-between padding">
<div id="flash-card-container" class="flex align-center column justify-between padding container">
<h2>Flash Card Viewer</h2>
<div id="flashcard" class="flex align-center justify-center padding card">
<div id="card-front"></div>
<div id="card-back" class="hidden"></div>
</div>
</div>
<div id="card-manager-container" class="flex align-center column center justify-between padding container">
<h2>Manage Cards</h2>
<form id="entry-form" class="card padding flex column justify-center align-center">
<h3>Add New Card</h3>
<label class="newcard-label font-bold" for="front-text">Front</label>
<textarea id="front-text" class="newcard-input"></textarea>
<label class="newcard-label font-bold" for="back-text">Back</label>
<textarea id="back-text" class="newcard-input"></textarea>
<button id="save-btn" class="button font-bold" type="submit">Save New Flash Card</button>
</form>
<div id="allcards-container" class="card padding">
<h3>All Cards</h3>
<div id="all-cards" class="card padding flex column justify-center align-center">
</div>
</div>
<button id="delete-btn" class="button font-bold">Delete Current Flash Card</button>
</div>
</main>
<footer class="flex column align-center section-width center padding justify-between">
<div id="links-container" class="flex column section-width">
<div id="about-us-container">
<h2>About Us</h2>
<ul class="font-normal">
<li><a href="#">What is Deki Deck?</a></li>
<li><a href="#">Why did I make Deki Deck?</a></li>
</ul>
</div>
<div id="resources-container">
<h2>Resources</h2>
<ul class="font-normal">
<li><a href="#">Frequently Asked Questions (FAQ)</a></li>
<li><a href="#">Totally Legit Deki Decks</a></li>
<li><a href="#">How to use Deki Deck</a></li>
</ul>
</div>
<div id="contact-us-container">
<h2>Contact Us</h2>
<ul class="font-normal">
<li>Email: <a href="#" class="contact-link">totallylegit@email.com</a></li>
<li>Cell: <a href="#" class="contact-link">+101 423 13223 345</a></li>
<li>Phone: <a href="#">+101 011 12143 233</a></li>
</ul>
</div>
</div>
<p>Deki Deck is a product made purely for educational purposes and is not an actual flashcard program.</p>
</footer>
<script src="index.ts"></script>
</body>
</html>
/* file: index.ts */
interface FlashCard {
questionText: string;
questionAnswer: string;
}
const STORAGE_KEY = "saved_cards";
let currentCards: FlashCard[] = [];
let currentCard = currentCards.length - 1;
function loadCards(): FlashCard[] {
try {
const saved = localStorage.getItem(STORAGE_KEY);
if (saved) {
return JSON.parse(saved);
}
} catch (error) {
console.log("Failed to load flash cards:", error);
}
return [];
}
function selectCard(index: number) {
currentCard = index;
handleCards();
}
function saveCards() {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(currentCards));
} catch (error) {
console.log("Failed to save flash card data:", error);
}
}
function handleCards() {
if (currentCard === -1) {
currentCard = currentCards.length - 1;
} else if (currentCard >= currentCards.length) {
currentCard = currentCards.length - 1;
}
if (currentCards.length >= 1) {
if (cardFront && cardBack) {
cardFront.textContent = currentCards[currentCard].questionText;
cardBack.textContent = currentCards[currentCard].questionAnswer
}
if (allCards) {
allCards.innerHTML = currentCards.map((card, index) => `<button data-index="${index}" class="button">${card.questionText.length > 20 ? `${card.questionText.slice(0, 21)}...` : card.questionText}</button>`).join("");
}
} else {
if (cardFront && cardBack && allCards) {
cardFront.textContent = "";
cardBack.textContent = "";
allCards.innerHTML = "";
}
}
}
const saveBtn = document.querySelector<HTMLInputElement>("#save-btn");
const deleteBtn = document.querySelector<HTMLButtonElement>("#delete-btn");
const flashcard = document.querySelector<HTMLElement>("#flashcard");
const cardFront = document.querySelector<HTMLElement>("#card-front");
const cardBack = document.querySelector<HTMLElement>("#card-back");
const frontText = document.querySelector<HTMLTextAreaElement>("#front-text");
const backText = document.querySelector<HTMLTextAreaElement>("#back-text");
const allCards = document.querySelector<HTMLElement>("#all-cards");
class InvalidUserInputError extends Error {
constructor(message: string) {
super(message);
this.name = 'InvalidUserInputError';
}
}
document.addEventListener("DOMContentLoaded", () => {
currentCards = loadCards();
handleCards();
});
if (saveBtn) {
saveBtn.addEventListener("click", (e) => {
e.preventDefault();
try {
if (frontText && backText) {
if (frontText.value === "" || backText.value === "") {
throw new InvalidUserInputError("Front or Back Text Missing");
}
currentCards = [...currentCards, {
questionText: frontText.value,
questionAnswer: backText.value,
}];
frontText.value = "";
backText.value = "";
saveCards();
handleCards();
}
} catch (error) {
if (error instanceof InvalidUserInputError) {
alert("The Front and Back of the flash card should both have values.");
} else {
console.error("Unexpected error:", error);
}
}
})
}
if (deleteBtn) {
deleteBtn.addEventListener("click", () => {
if (currentCards.length >= 1) {
currentCards = currentCards.filter((_, index) => index !== currentCard);
if (flashcard) {
flashcard.classList.toggle("flipped");
}
if (currentCards.length === 0) {
currentCard = -1;
} else if (currentCard >= currentCards.length) {
currentCard = currentCards.length - 1;
}
saveCards();
handleCards();
}
})
}
if (allCards) {
allCards.addEventListener("click", (e) => {
const button = (e.target as HTMLElement).closest("button");
if (button) {
const index = parseInt(button.getAttribute("data-index") || "0");
selectCard(index);
}
});
}
if (flashcard && cardFront && cardBack) {
flashcard.addEventListener("click", () => flashcard.classList.add("flipped"));
flashcard.addEventListener("mouseenter", () => {
if (flashcard.classList.contains("flipped")) {
cardBack.classList.toggle("hidden");
cardFront.classList.toggle("hidden");
}
});
flashcard.addEventListener("mouseleave", () => {
if (flashcard.classList.contains("flipped")) {
cardBack.classList.toggle("hidden");
cardFront.classList.toggle("hidden");
}
});
}
/* file: styles.css */
/* General Styling */
:root {
/* Color Variables */
--main-background : #090912;
--flash-card-container-background: #121222;
--delete-button-background: #CC0066;
--main-text: #DFDFEF;
--logo-text: #0066CC;
--footer-text: #BFBFCF;
--footer-link-hover-text: #BFBFDF;
--main-header-text: #006BCC;
--secondary-header-text: #007ACC;
--button-text: #09091F;
--main-border-color: #002B5C;
--secondary-border-color: #003DA5;
--delete-button-border-color: #A5003D;
/* Size Variables */
--header-height: 3rem;
--footer-height: 20rem;
--main-section-height: 68rem;
--container-width: 100%;
--flashcard-container-height: 24rem;
--card-width: 95%;
--flashcard-height: 20rem;
--manage-container-height: 42.5rem;
--newcard-container-height: 20rem;
--allcards-container-height: 15rem;
--newcard-input-width: 90%;
--newcard-input-height: 4rem;
--border-main-size: 0.2rem;
--border-secondary-size: 0.15rem;
--user-avatar-size: 70%;
--logo-star-size: .7rem;
--lr-padding: 0.5rem;
--padding: 0.5rem;
--logo-font-size: 1.2rem;
--footer-heading-size: 1.1rem;
--footer-text-size: .8rem;
--main-section-text-size: 1rem;
--main-header-text-size: 1.4rem;
--secondary-header-text-size: 1.1rem;
--button-text-size: 0.85rem;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: 17.6px;
}
body {
background-color: var(--main-background);
color: var(--main-text);
width: 100%;
font-family: "Poppins", 'Arial Black', Gadget, sans-serif;
position: relative;
}
.flex {
display: flex;
}
.column {
flex-direction: column;
}
.align-center {
align-items: center;
}
.justify-between {
justify-content: space-between;
}
.justify-center {
justify-content: center;
}
.section-width {
width: 100%;
}
.font-normal {
font-weight: 500;
}
.font-bold {
font-weight: 600;
}
.center {
text-align: center;
}
.lr-padding {
padding: 0 var(--lr-padding);
}
.padding {
padding: var(--padding);
}
a {
text-decoration: none;
color: var(--text-color);
}
a:hover {
color: var(--footer-link-hover-text);
}
ul {
list-style: none;
}
.hidden {
display: none;
}
/* Header Styling */
header {
height: var(--header-height);
border-bottom: var(--border-main-size) solid var(--main-border-color);
position: sticky;
top: 0;
background-color: var(--main-background);
z-index: 1;
}
#logo {
font-family: 'Righteous', 'Arial Black', Gadget, sans-serif;
font-size: var(--logo-font-size);
font-weight: 400;
color: var(--logo-text);
line-height: .5
}
#logo:after {
font-size: var(--logo-star-size);
content: "★ ☆";
white-space: pre-wrap;
display: block;
line-height: 0;
}
#logo:before {
font-size: var(--logo-star-size);
content: "☆ ★";
white-space: pre-wrap;
display: block;
line-height: 0;
}
#user-avatar-link {
display: inline-block;
height: var(--user-avatar-size);
}
#user-avatar {
height: 100%;
border-radius: 50%;
border: var(--border-secondary-size) outset var(--secondary-border-color)
}
/* Main Section Styling */
main {
height: var(--main-section-height);
font-size: var(--main-section-text-size);
}
main h2 {
color: var(--main-header-text);
font-size: var(--main-header-text-size);
}
.container {
background-color: var(--flash-card-container-background);
width: var(--container-width);
border-radius: .4rem;
}
.card {
background-color: var(--main-background);
border-radius: .6rem;
width: var(--card-width);
}
#flash-card-container {
height: var(--flashcard-container-height);
}
#flashcard {
height: var(--flashcard-height);
transition: transform 0.5s;
transform-style: preserve-3d;
word-break: break-all;
}
.flipped {
transform: perspective(1000px) rotateY(180deg);
}
#card-back {
transform: rotateY(180deg);
}
#flashcard:hover {
cursor: pointer;
transform: translateY(-.5rem);
}
#card-manager-container {
height: var(--manage-container-height);
}
#entry-form {
height: var(--newcard-container-height);
overflow-y: auto;
gap: .7rem;
}
.newcard-label {
color: var(--secondary-header-text);
font-size: var(--secondary-header-text-size);
}
.newcard-input {
width: var(--newcard-input-width);
height: var(--newcard-input-height);
resize: vertical;
border-radius: .8rem;
padding: .3rem;
font-size: var(--main-section-text-size);
flex-shrink: 0;
}
#allcards-container {
height: var(--allcards-container-height);
overflow-y: auto;
}
.button {
border-radius: 10rem;
padding: .6rem;
color: var(--button-text);
font-size: var(--button-text-size);
background-color: var(--main-header-text);
border: var(--border-secondary-size) outset var(--secondary-header-text);
margin: 0.1rem;
}
.button:hover {
cursor: pointer;
filter: brightness(1.2);
}
.button:focus {
outline: var(--border-secondary-size) outset var(--main-text);
}
#delete-btn {
background-color: var(--delete-button-background);
border-color: var(--delete-button-border-color);
}
/* Footer Styling */
footer {
color: var(--footer-text);
height: var(--footer-height);
border-top: var(--border-main-size) solid var(--main-border-color);
font-size: var(--footer-text-size);
}
#links-container h2 {
font-size: var(--footer-heading-size);
}
@media (min-width: 768px) {
:root {
--footer-height: 9rem;
--container-width: 60%;
--main-section-height: 70rem;
--manage-container-height: 44.5rem;
--newcard-container-height: 22rem;
--main-section-text-size: 1.2rem;
--main-header-text-size: 1.8rem;
--secondary-header-text-size: 1.4rem;
--button-text-size: 0.95rem;
}
#links-container {
flex-direction: row;
justify-content: space-evenly;
align-items: space-evenly;
}
}
@media (min-width: 1024px) {
:root {
--footer-height: 9rem;
--container-width: 60%;
--main-section-height: 70rem;
--manage-container-height: 44.5rem;
--newcard-container-height: 22rem;
--main-section-text-size: 1.2rem;
--main-header-text-size: 1.8rem;
--secondary-header-text-size: 1.4rem;
--button-text-size: 0.95rem;
}
#links-container {
flex-direction: row;
justify-content: space-evenly;
align-items: space-evenly;
}
}
Your browser information:
User Agent is: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36
Challenge Information:
Build a Flashcard Quiz App - Build a Flashcard Quiz App