Build a Customer Complaint Form

Tell us what’s happening:

It seems like my code has a subtle bug in it! as the test number 15,16 and 23,24 failing!

15 - Once one checkbox from #complaints-group is checked, you should set #complaints-group’s border color to green.

16 - When all of the checkboxes from #complaints-group are changed to the unchecked state, you should set #complaints-group’s border color to red.

23 - Once a radio button from #solutions-group is checked, you should set #solutions-group’s border color to green.

24 - When all of the checkboxes from #complaints-group are changed to the unchecked state, you should set #complaints-group’s border color to red.

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">

<head>
    <title>Customer Complaint Form</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="styles.css">
</head>

<body>
    <h1>Complaint Form</h1>
    <form id="form">
        <fieldset id="personal-info">
            <div>
                <label for="full-name">Full Name:</label>
                <input type="text" id="full-name" name="full-name" placeholder="John Doe" required>
            </div>

            <div>
                <label for="email">Email Address:</label>
                <input type="email" id="email" name="email" placeholder="example@domain.com">
            </div>
        </fieldset>
        <hr>
        <fieldset id="product-info">
            <div>
                <label for="order-no">Order No:</label>
                <input type="text" id="order-no" name="order-no" placeholder="2024######">
            </div>
            <div>
                <label for="product-code">Product Code:</label>
                <input type="text" id="product-code" name="product-code" placeholder="XX##-X###-XX#">
            </div>
            <div>
                <label for="quantity">Quantity:</label>
                <input type="number" id="quantity" name="quantity" min="1">
            </div>
        </fieldset>

        <fieldset id="complaints-group">
            <legend>Complaint Reason:</legend>
            <div>
                <input type="checkbox" id="damaged-product" name="complaint" value="damaged-product">
                <label for="damaged-product">Damaged Product</label>
            </div>

            <div>
                <input type="checkbox" id="nonconforming-product" name="complaint" value="nonconforming-product">
                <label for="nonconforming-product">Nonconforming Product</label>
            </div>

            <div>
                <input type="checkbox" id="delayed-dispatch" name="complaint" value="delayed-dispatch">
                <label for="delayed-dispatch">Delayed Dispatch</label>
            </div>

            <div>
                <input type="checkbox" id="other-complaint" name="complaint" value="other">
                <label for="other-complaint">Other</label>
            </div>
        </fieldset>

        <div id="complaint-description-container">
            <legend>Description of Complaint Reason</legend>
            <textarea placeholder="Describe the reason of your complaint in at least 20 characters"
                name="complaint-textarea" id="complaint-description"></textarea>
        </div>

        <fieldset id="solutions-group">
            <legend>Desired Solution</legend>
            <input type="radio" name="solutions" id="refund" value="refund">
            <label for="refund">Refund</label>

            <input type="radio" name="solutions" id="exchange" value="exchange">
            <label for="exchange">Exchange</label>

            <input type="radio" name="solutions" id="other-solution" value="other">
            <label for="other-solution">Other</label>
        </fieldset>

        <div id="solution-description-container">
            <legend>Description of Desired Solution</legend>
            <textarea placeholder="Describe the desired solution to your issue in at least 20 characters"
                name="solution-textarea" id="solution-description"></textarea>
        </div>
        <div id="btn-container">
            <button type="submit" id="submit-btn">Submit</button>
            <span id="message-box"></span>
        </div>

    </form>

    <script src="script.js"></script>
</body>

</html>
/* file: styles.css */
:root {
    --light-grey: #f5f6f7;
    --dark-blue: #0a0a23;
    --fcc-blue: #1b1b32;
    --light-yellow: #fecc4c;
    --dark-yellow: #feac32;
    --light-pink: #ffadad;
    --dark-red: #850000;
    --light-green: #acd157;
}

body {
    font-family: "Lato", Helvetica, Arial, sans-serif;
    font-size: 18px;
    background-color: var(--fcc-blue);
    color: var(--light-grey);
}

h1 {
    text-align: center;
}

.container {
    width: 90%;
    max-width: 680px;
}

h1,
.container,
.output {
    margin: 20px auto;
}

label,
legend {
    font-weight: bold;
}

.input-container {
    display: flex;
    flex-direction: column;
}

button {
    cursor: pointer;
    text-decoration: none;
    background-color: var(--light-yellow);
    border: 2px solid var(--dark-yellow);
}

button,
input,
select {
    min-height: 24px;
    color: var(--dark-blue);
}

fieldset,
label,
button,
input,
select {
    margin-bottom: 10px;
}

.output {
    border: 2px solid var(--light-grey);
    padding: 10px;
    text-align: center;
}

.hide {
    display: none;
}

.output span {
    font-weight: bold;
    font-size: 1.2em;
}

.surplus {
    color: var(--light-pink);
}

.deficit {
    color: var(--light-green);
}
/* file: script.js */
const complaintForm = document.getElementById('form');


function nameValidator(str) {
    return str.trim() !== ""
}

function emailValidator(str) {
    const pattern = /\w+@\w+\.\w+/i // acceptable email = a@b.c
    return pattern.test(str)
}

function orderNumberValidator(str) {
    const pattern = /2024\d{6}/
    return pattern.test(str)
}

function productCodeValidator(str) {
    const pattern = /[a-z]{2}\d{2}-[a-z]\d{3}-[a-z]{2}\d/i
    return pattern.test(str)
}

function productQuantityValidator(str) {
    return Number(str) > 0
}

function complaintValidator() {
    const complaintReasons = document.querySelectorAll('input[type="checkbox"]');
    const otherReason = document.getElementById("other-complaint")
    const complaintContainer = document.getElementById("complaint-description-container")
    // hiding and showing the element as needed
    complaintContainer.style.display = otherReason.checked? "block" : "none";
    // we can create an array or use some array functions on this NodeList
    return Array.from(complaintReasons).some(reason => reason.checked);
}

function customComplaintValidator(str) {
    const otherReason = document.getElementById("other-complaint")
    return otherReason.checked && str.length >= 20  || (!otherReason.checked);
}

function solutionValidator() {
    const solutions = document.querySelectorAll('input[type="radio"]');
    const otherSolution = document.getElementById("other-solution");
    const solutionsContainer = document.getElementById("solution-description-container");
    // hiding and showing the element as needed
    solutionsContainer.style.display = otherSolution.checked? "block" : "none";
    // we can create an array or use some array functions on this NodeList
    return Array.from(solutions).some(reason => reason.checked);
}

function customSolutionValidator(str) {
    const otherSolution = document.getElementById("other-solution");
    return (otherSolution.checked && str.length >= 20) || (!otherSolution.checked);
}

function validateForm() {
    // getting the elements
    const fullName = document.getElementById("full-name")
    const emailAddress = document.getElementById("email")
    const orderNumber = document.getElementById("order-no")
    const productCode = document.getElementById("product-code")
    const productQuantity = document.getElementById("quantity")
    const complaintDescription = document.getElementById("complaint-description")
    const solutionDescription = document.getElementById("solution-description")

    // return object containing keys and values as booleans
    return {
        "full-name": nameValidator(fullName.value),
        "email": emailValidator(emailAddress.value),
        "order-no": orderNumberValidator(orderNumber.value),
        "product-code": productCodeValidator(productCode.value),
        "quantity": productQuantityValidator(productQuantity.value),
        "complaints-group": complaintValidator(),
        "complaint-description": customComplaintValidator(complaintDescription.value),
        "solutions-group": solutionValidator(),
        "solution-description": customSolutionValidator(solutionDescription.value),
    };
}


function isValid(ob) {
    return Object.values(ob).every(value => value === true);
}


complaintForm.addEventListener("change", (e) => {
    e.stopPropagation();
    const complaintReasons = ["damaged-product", "nonconforming-product", "delayed-dispatch", "other-complaint"]
    const solutions = ["refund", "exchange", "other-solution"]

    if (e.target.id === "full-name") {
        e.target.style.borderColor = nameValidator(e.target.value)? "green" : "red";

    } else if (e.target.id === "email") {
        e.target.style.borderColor = emailValidator(e.target.value)? "green" : "red";

    } else if (e.target.id === "order-no") {
        e.target.style.borderColor = orderNumberValidator(e.target.value)? "green" : "red";

    } else if (e.target.id === "product-code") {
        e.target.style.borderColor = productCodeValidator(e.target.value)? "green" : "red";

    } else if (e.target.id === "quantity") {
        e.target.style.borderColor = productQuantityValidator(e.target.value)? "green" : "red";

    } else if (complaintReasons.includes(e.target.id)) {
        const fieldset = e.target.closest('fieldset');
        fieldset.style.borderColor = complaintValidator()? "green" : "red";

    } else if (e.target.id === "complaint-description") {
        e.target.style.borderColor = customComplaintValidator(e.target.value)? "green" : "red";

    } else if (solutions.includes(e.target.id)) {
        const fieldset = e.target.closest('fieldset');
        fieldset.style.borderColor = solutionValidator()? "green" : "red";

    } else if (e.target.id === "solution-description") {
        e.target.style.borderColor = customSolutionValidator(e.target.value)? "green" : "red";
    }
})

// it seems like my code has a very subtle bug in it! as it can't pass 15,16 and 23,24 tests
complaintForm.addEventListener("submit", (e) => {
    e.preventDefault();

    if (isValid(validateForm())) {
        console.log(validateForm());
        console.log("Form is valid");
    } else {
        console.log(validateForm());
        console.log(validateForm)
        console.log("Form is invalid");
    }
})

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101 Firefox/135.0

Challenge Information:

Build a Customer Complaint Form - Build a Customer Complaint Form

Looks like you might have encountered bug, caused by fact that during test individual checked attributes of the checkboxes/radios are modified, but the change event is dispatched on the parent fieldset, not the modified element itself.

Would you be interested in creating issue for this problem on freeCodeCamp’s GitHub repository?

hi, yeah sure but I don’t necessarily know the technical know-how of what is acceptable input what is not.

It doesn’t need to be written very technical. As long as you follow the issue form and provide the context - what happens, when, what should happen instead - it will be enough to report the problem. You can also link to this thread.