As the digital sun sets on the horizon, a new chapter emerges in my journey as a web developer. Today marks the culmination of a remarkable project: the creation of an enchanting HTML and CSS e-commerce payment gateway page. In the realm where code meets creativity, this accomplishment radiates like a beacon of innovation and user-centric design. Every line of code written, every pixel meticulously placed, has woven together an online tapestry where seamless functionality dances with aesthetic allure. This achievement isn't just about crafting lines of HTML and CSS; it's about sculpting an immersive experience where users can seamlessly transition from shopping cart to checkout with confidence. Through countless iterations and the skillful mastery of design elements, I've given life to a digital marketplace that embodies the spirit of modern commerce. As the final pixel finds its perfect position, I reflect on the fusion of technical prowess and artistic expression that has brought this project to life. This e-commerce masterpiece isn't just about colors and typography; it's about creating a canvas where user journeys are intuitive and transactions are secure. With this achievement, I join the ranks of digital artisans, forging pathways for seamless online interactions. This project isn't just a collection of web pages; it's a gateway to a new realm of possibilities in the ever-evolving landscape of digital experiences. Just as HTML and CSS lay the foundation, this project lays the groundwork for a future where online shopping is not just a transaction, but an engaging voyage. As the virtual shopping cart transforms into a virtual checkout counter, I take pride in contributing to the digital evolution, one elegantly coded page at a time.
nicodes
@nicodes-devAll comments
- @abdulabhiSubmitted over 1 year ago@nicodes-devPosted over 1 year ago
Hi, I feel like you may have rushed your solution and did not test it before submitting because the page only looks okay on desktop screen width because you use translate to center your container but use a negative value.
top: -50%;
There are also styles in your container that does not work. I assume you want to use flex because you added flex-direction.
.container { //forgot to add display: flex; background-color: #fff; width: 450px; align-items: center; flex-direction: column; text-align: center; justify-content: center; border-radius: 8px; box-shadow: 0px 4px 8px var(--desaturated_blue); position: relative; top: -50%; left: 50%; margin-top: 30%; transform: translate(-50%, -50%); }
To center your container, you can use grid or flex and add it into the body. Also add a min-height to your body to cover the whole viewport.
using flex
body { min-height: 100vh; display: flex; align-items: center; justify-content: center; flex-direction: column; }
using grid
body { min-height: 100vh; display: grid; align-content: center; justify-content: center; }
Then your container styles should look like this.
.container { background-color: #fff; width: 450px; border-radius: 8px; box-shadow: 0px 4px 8px var(--desaturated_blue); }
I hope this helps you fix your solution.
0 - @Kingnorj1Submitted over 1 year ago
Responsive. Code corrections are welcomed
@nicodes-devPosted over 1 year agoHi Big-Norj! You did a good job with your solution although I found some mistakes in your code. First is that if you hover on the "Learn more" button, the font changes.
This is because you set it to font-family: bold
.hero button:hover { background-color: transparent; border: 1px solid black; color: grey; font-family: bold; // this should be font-weight: bold or 700 cursor: pointer; transition: all 1s; }
You should also only add transition to properties that you want to transition.
transition: all 1s;
You can add multiple transition by separating them by comma (,)
transition: background-color 250ms, color 250ms;
Another thing you may want to fix is your mobile nav appears when the width of the screen is at 900px. I would like to help you with it but your github repo is hard to clone. The problem is your solutions are added in multiple branch.
I suggest that in the future challenges. When you add new solutions, you add it all in the main branch.
Marked as helpful0 - @LuccaMauroMolinaSubmitted over 1 year ago
Good evening, how do I do so that when I'm not selected an alert skips and when I'm selected the number skips, I did it both ways but when I do it in one it works for me and if I put another the other works for me! how would it be?
@nicodes-devPosted over 1 year agoHi Lucca! In your code, you do not have an element with an id 'no select'.
const create = document.getElementById('no select')
So this code assigns a null value in your variable create. Thus in your if else statement, it will always be true.
// boton.addEventListener('click', () => { // const create = document.getElementById('no select') //returns null // if (create === null) { //null === null // alert('selecciona un valor') // } else { // centro2.classList.remove('.segundo') // centro1.style.display = 'none' // centro2.style.display = 'flex' // } // })
On your other if else statement, you are using a logical AND (&& ) operator to test two conditions.
create === null && create === botones
This will always return false, so only the else statement will be applied.
boton.addEventListener('click', () => { const create = document.getElementById('no select') if (create === null && create === botones) { //always false alert('selecciona un valor') } else { centro2.classList.remove('.segundo') centro1.style.display = 'none' centro2.style.display = 'flex' } })
A simple fix is to use the element which you display when a button is clicked. You can check if its innerHTML is not an empty string.
Numero.innerHTML.length === 0
You can't check if it is null because the type of Numero.innerHTML is a string
console.log(typeof Numero.innerHTML) //returns string
Now your code should be working fine if you use this in your if else statement.
boton.addEventListener('click', () => { if (Numero.innerHTML.length === 0) { alert('selecciona un valor') } else { centro2.classList.remove('.segundo') centro1.style.display = 'none' centro2.style.display = 'flex' } })
I hope this helps you with your solution.
Marked as helpful0 - @elic4vetSubmitted over 1 year ago
I have a problem with the buttons, i cannot select just only one although i used useState and other methods. Once clicked every button is selected. Could you please help me ?
@nicodes-devPosted over 1 year agoHi Elisabeth! I'm non-native english speaker so please bear with me. I review your code and it seems like you are a beginner in React but I assume you know "props" and "state". First let's identify what is the problem.
"I cannot select just only one although i used useState and other methods. Once clicked every button is selected."
The buttons are working fine, the problem is that the class "selected" applies to all buttons because of the conditional statement in the className.
className={isActive ? "selected" : ""}
In your code, isActive is a boolean which you set to true if "any" button is clicked, so all the buttons have the class 'selected' applied to it.
To fix this, use the selectedNumber state instead.
className={selectedNumber === '1' ? 'selected' : ''} //the class will only apply to the button which holds the value 1
You are also passing the whole event object in setSelectedNumber and you only use extract the value in the <p> tag.
const handleClick = (numberSelected) => { setSelectedNumber(numberSelected) } <p className="result">You selected {selectedNumber.target.value} out of 5</p>
To fix this, you should extract the value and pass it in the setSelectedNumber.
const handleClick = (event) => { const value = event.target.value setSelectedNumber(value ) } <p className="result">You selected {selectedNumber} out of 5</p>
The snippets above should be able to fix the problem.
Now to help you clean your code, I have written the snippets below.
This might be too long so you can just paste it in your code and then review it.
In your Rating component, you initialize the selectedNumber as a number which value is 0.
const [selectedNumber, setSelectedNumber] = useState(0);
When you get the value from the event object, any value will be converted to a string. So you can just initialize it with an empty string.
const [selectedNumber, setSelectedNumber] = useState("");
Then you can remove the isActive state because we will be using the selectedNumber to add the "selected" class. You also have to change the handleSubmit function. Your code should look like this
const [selectedNumber, setSelectedNumber] = useState(") const [success, setSuccess] = useState(false) const handleClick = event => { setSelectedNumber(event.target.value) } const handleSubmit = () => { // you can just check the length we initialize selectedNumber as a string. if (selectedNumber.length === 0) { alert('Please select a rating!') } else { setSuccess(true) } }
You can also remove this line of codes since this is not the proper way to write inline styles in react.
let rating_app = document.querySelector('.rating_app') let submit_btn = document.querySelector('.submit-btn') rating_app.style.display = 'none' submit_btn.style.display = 'none'
You can directly apply it to the element without having to use a querySelector.
let successComponent = null if (success) { successComponent = ( <div> <img src={img}/> <p className="result">You selected {selectedNumber} out of 5</p> <h1>Thank you !</h1> <p>We appreciate you taking the time to give a rating. If you ever need more support, don't hesitate to get in touch!</p> </div> ) }
Then in the return statement, we will use a ternary operator to render either successComponent or the rating div. Note: I remove the key and id attribute in your button because it is not needed in this solution.
return ( <div className="container"> <div className="card"> {success ? ( <div className="successComponent">{successComponent}</div> ) : ( <> <div className="rating_app"> <img src={icon} className="icon" alt="icon" /> <h1>How did we do ? </h1> <p>Please let us know how we did with your support request. All feedback is appreciated to help us improve our offering!</p> <div className="ratings"> <div className="circle"> <button className={setSelectedNumber === '1' ? 'selected' : ''} onClick={handleClick} value="1" > 1 </button> </div> <div className="circle"> <button className={setSelectedNumber === '2' ? 'selected' : ''} onClick={handleClick} value="2" > 2 </button> </div> <div className="circle"> <button className={setSelectedNumber === '3' ? 'selected' : ''} onClick={handleClick} value="3" > 3 </button> </div> <div className="circle"> <button className={setSelectedNumber === '4' ? 'selected' : ''} onClick={handleClick} value="4" > 4 </button> </div> <div className="circle"> <button className={setSelectedNumber === '5' ? 'selected' : ''} onClick={handleClick} value="5" > 5 </button> </div> </div> </div> <button className="submit-btn" onClick={handleSubmit}> Submit </button> </> )} </div>
You can also store the values that you are going to use in the buttons in an array and then map it's value.
const btnArrays = ['1', '2', '3', '4', '5'].map((value, index) => { return ( <div className="circle" key={index}> <button className={selectedNumber === value ? 'selected' : ''} onClick={handleClick} value={value} > {value} </button> </div> ) })
Then use it to render the buttons.
return ( <div className="container"> <div className="card"> {success ? ( <div className="successComponent">{successComponent}</div> ) : ( <> <div className="rating_app"> <img src={icon} className="icon" alt="icon" /> <h1>How did we do ? </h1> <p> Please let us know how we did with your support request. All feedback is appreciated to help us improve our offering! </p> <p className="results"></p> <div className="ratings">{btnArrays}</div> </div> <button className="submit-btn" onClick={handleSubmit}> Submit{' '} </button> </> )} </div> )
You can also separate the successComponent and btnsArray into another component. Then pass down the values you wish to pass to the component as props, remember that the Rating component holds the states.
ButtonComponents.jsx
const btnArrays = ['1', '2', '3', '4', '5'] const ButtonComponent = ({ selectedNumber, handleClick }) => { return btnArrays.map((value, index) => { return ( <div className="circle" key={index}> <button className={selectedNumber === value ? 'selected' : ''} onClick={handleClick} value={value} > {value} </button> </div> ) }) } export default ButtonComponent
SuccessComponent.jsx
const SuccessComponent = ({ img, selectedNumber }) => { return ( <div className="successComponent"> <div> <img src={img}></img> <p className="result">You selected {selectedNumber} out of 5</p> <h1>Thank you !</h1> <p> We appreciate you taking the time to give a rating. If you ever need more support, don't hesitate to get in touch! </p> </div> </div> ) } export default SuccessComponent
Then your Rating component should look like this.
Rating.jsx
import { useState } from 'react' import icon from '../assets/images/icon-star.svg' import img from '.././assets/images/illustration-thank-you.svg' import '../App.css' import ButtonComponent from './ButtonComponent' import SuccessComponent from './SucessComponent' const Rating = () => { const [selectedNumber, setSelectedNumber] = useState('') const [success, setSuccess] = useState(false) const handleClick = event => { setSelectedNumber(event.target.value) } const handleSubmit = () => { if (selectedNumber.length === 0) { alert('Please select a rating!') } else { setSuccess(true) } } return ( <div className="container"> <div className="card"> {success ? ( <SuccessComponent img={img} selectedNumber={selectedNumber} /> ) : ( <> <div className="rating_app"> <img src={icon} className="icon" alt="icon" /> <h1>How did we do ? </h1> <p> Please let us know how we did with your support request. All feedback is appreciated to help us improve our offering! </p> <p className="results"></p> <div className="ratings"> { <ButtonComponent handleClick={handleClick} selectedNumber={selectedNumber} /> } </div> </div> <button className="submit-btn" onClick={handleSubmit}> Submit{' '} </button> </> )} </div> ) } export default Rating
and finally, your App.jsx should not have any state, since your declare those in the Rating component.
import { React, useState } from 'react' import Rating from './components/Rating.jsx' import './App.css' function App() { //const [success, setSuccess] = useState(true); //const [selectedNumber, setSelectedNumber] = useState(0); return ( <> <Rating /> </> ) } export default App
You can copy and paste all those snippets since I tested it first.
Marked as helpful3 - @VickyAzolaSubmitted over 1 year ago
Any feedback is appreciated!
I had some difficulties doing and centeryn the circle using Tailwind, so decided to use CSS instead. If you know a way to do it with tailwind please let me know
Thanks!
@nicodes-devPosted over 1 year agoHi Victoria, two ways that you could use to center your circle is by adding a display flex or grid on it's parent element.
//css flex display: flex; flex-direction: column; justify-content: center; align-items: center; //css grid display: grid; place-items: center; place-content: center; //tailwind flex flex flex-col justify-center items-center //tailwind grid grid place-content-center place-items-center
then you can remove the margin from your circle
Marked as helpful0 - @gabrieltrtSubmitted over 1 year ago
Hello friends, here is the conclusion of another WEF challenge. I hope I can get good feedback from you and improve my front-end every day.
@nicodes-devPosted over 1 year agoYou did a great job, it looks exactly as the design.
- You missed adding a box shadow to your <main> tag.
- I also suggest that you use an <a/> tag or a <button> tag instead of <p> tag for the Cancel Order since this is suppose to be a redirect or CTA.
- Hover effect are also missing in your solution.
0 - @LooceeSubmitted over 2 years ago
I learned to use JavaScript for DOM manipulation. I learned some new CSS properties like letter spacing which I used in the "submit" button. I also worked on using more standard units like "rem" and "%". In this project, I made use of some inline styles and did the rest in my stylesheet. Basically the frustrating part of this project was determining the exact color of the rating buttons(I had to go through some people's project to get the color, it was different from what was provided in the challenge style-guide.md). This is my first time using JavaScript/jQuery on my own without my tutor's guidance, so I'm proud of what I did. I also put a default rating in situations whereby the client didn't choose any value.
@nicodes-devPosted over 2 years agoHi! I have a few suggestions for your solution.
-
In this challenge it is not bad to add a default rating if the user didn't select a rating and clicked submit but I think it is better if you'll add a simple validation that won't allow the user to submit it without selecting a rating or you can also add an error message that tells the user that they haven't selected a rating before clicking submit.
-
I notice that in your media query, you use a max-width of 375px. Is this intended to only be displayed on a mobile device? If not, maybe you can try to make it responsive with adding more media query. I suggest that you use a min-width of 320px or 360px and just add a max-width on your parent container so it won't stretch too much.
-
The active class is not working properly, the background color and color only apply after selecting another button and it also allow multiple ratings to get an active class. You can use a loop to check whether your button should have an active class. You should use addClass and removeClass instead of toggleClass for this to work.
Marked as helpful0 -
- @Georgecip1Submitted over 2 years ago
I've had problems with making the landing page work from a wider view than from a "phone" perspective.
@nicodes-devPosted over 2 years agoHi George! Your mistake is using percentage in the max-width of your content class. I suggest that you use a fixed unit in your max-width.
@media (min-width: 440px) { //other styles .content { max-width: 500px; //you can also use rem, em } }
You can also use clamp in your width, then you won't need to add a media query for it.
// clamp(MIN, VAL, MAX) width: clamp(300px, 90%, 500px);
You can learn more about clamp in the official docs. clamp
You also need to add a <main> tag in your solution. You can just replace the div tag of your content class.
<main class="content"> .... </main>
Feel free to ask if you have any question.
1 - @Yoseif-Alfiky-1Submitted over 2 years ago
when i make the screen smaller , the blue color appear in the background , Could anyone help me to solve this problem . and this is a link ---"https://yoseif-alfiky-1.github.io/Card-Component/"-- the transparent blue appear when the item move . Good luck for everyone.
@nicodes-devPosted over 2 years agoYou have a background-color in your contact class.
.contact { // other styles background-color: azure; }
You need to set a <main> semantic tag inorder to fix your error reports. You can replace the section or wrap it with a main tag and add an id or class to it.
<main class="main"> <div class="box">...</div> <div class="box">...</div> <div class="box">...</div> </main>
You also need to add an alt attribute on all of your image tags. This is helpful for screen readers.
<img src="images/icon-sedans.svg" alt="sedans">
I hope this will help.
Marked as helpful0 - @DanoBrozSubmitted over 2 years ago
Hello, coding community 👋
I had a lot of fun with this challenge 🤥😅. It was supposed to be a small challenge for start, but in the end it turned out to be great eye-opener 😳. This little side project reminded me to look into Fetch API, Promises and Typescript.
I'm not quite sure of my custom search hook and the way I use it, I'd love to hear some best practices or more ideas of how to improve it.
Also I'd be happy to know your opinion about:
- tailwind class-based styling: are you more for inline styling or writing it in separate file?
- rendering elements based on props (based on href to be more specific) (ex. UserLink component in my solution) - is there a better solution, or do you use it the same way?
If you'll find any other ways to improve my code, please be sure to reach out here or in the slack channel.
@nicodes-devPosted over 2 years agoHi Daniel! You've done a great job on this challenge. Only thing I think that is missing is the opacity when the link is unavailable, overall it looks great.
// In your App.tsx const [searchData, setSearchData] = useState<DefaultData>(defaultData) useEffect(() => { setSearchData(defaultData) }, [])
You already set the default value of searchData to defaultData so I don't think the useEffect is still needed. But you can improve this by passing your fetch function to search for the default user inside useEffect.
// In App.tsx useEffect(() => { const asyncFn = async = () => { await handleSubmit('octocat') } asyncFn() },[handleSubmit]
But if you pass your handleSubmit function inside useEffect, you need to memoize it by wrapping it in a useCallback hook because it will cause an infinite loop inside the useEffect.
// In useSearchSubmit hook const handleSubmit = useCallback (async() => { // all your codes } ,[])
I haven't learn typescript yet but I hope this is still helpful.
1