├── README.md ├── index.html └── js ├── app.js └── summary.js /README.md: -------------------------------------------------------------------------------- 1 | # phone-hunter 2 | 3 | ## API Links 4 | 5 | ### Phone Search 6 | URL Format: https://openapi.programming-hero.com/api/phones?search=${searchText} 7 | 8 | Example: https://openapi.programming-hero.com/api/phones?search=iphone 9 | 10 | 11 | ### Phone detail url: 12 | URL Format: https://openapi.programming-hero.com/api/phone/${id} 13 | 14 | 15 | Example: https://openapi.programming-hero.com/api/phone/apple_iphone_13_pro_max-11089 16 | 17 | 18 | ## issue List 19 | 1. Search button not working 20 | 2. after typing something on the search textbox, you should be able to press enter to get search result 21 | 3. spinner is always running. should be displayed at the time of data loading 22 | 4. If you search for 'iphone', check the api, you should get a lot of data but the UI displays only one phone 23 | 5. Search is not clearing previous results 24 | 6. picture of the phones are not showing 25 | 7. Show All button should be hidden after all data is loaded 26 | 8. Load phone details doesn't display anything 27 | 9. Phone details are added on the modal but this is not getting displayed. why? 28 | 10. Storage on Modal isn't getting displayed properly 29 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Phone Hunter 8 | 10 | 11 | 12 | 13 |
14 |

Welcome to my Phone Hunter!

15 |
16 |
17 |
18 |
19 | 21 | 22 |
23 |
24 | 25 |
26 |
27 |
28 | Loading... 29 |
30 |
31 |
32 | 33 |
34 |
35 | 36 |
37 |
38 |

No Phone Found. Please try a new search

39 |
40 |
41 |
Show All
42 |
43 |
44 | 45 | 46 |
47 | 48 | 49 | 66 |
67 |
68 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /js/app.js: -------------------------------------------------------------------------------- 1 | const loadPhones = async(searchText, dataLimit) =>{ 2 | const url = `https://openapi.programming-hero.com/api/phones?search=${searchText}` 3 | const res = await fetch(url); 4 | const data = await res.json(); 5 | displayPhones(data.data, dataLimit); 6 | } 7 | 8 | const displayPhones = (phones, dataLimit) =>{ 9 | const phonesContainer = document.getElementById('phones-container'); 10 | // phonesContainer.textContent = ''; 11 | // display 10 phones only 12 | const showAll = document.getElementById('show-all'); 13 | if(dataLimit && phones.length > 10) { 14 | phones = phones.slice(0, 10); 15 | showAll.classList.remove('d-none'); 16 | } 17 | else{ 18 | showAll.classList.add('d-hidden'); 19 | } 20 | 21 | 22 | // display no phones found 23 | const noPhone = document.getElementById('no-found-message'); 24 | if(phones.length === 0){ 25 | noPhone.classList.remove('d-none'); 26 | } 27 | else{ 28 | noPhone.classList.add('d-none'); 29 | } 30 | // display all phones 31 | phones.forEach(phone =>{ 32 | const phoneDiv = document.createElement('div'); 33 | phoneDiv.classList.add('col'); 34 | phonesContainer.innerHTML = ` 35 |
36 | ... 37 |
38 |
${phone.phone_name}
39 |

This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

40 | 41 | 42 |
43 |
44 | `; 45 | phonesContainer.appendChild(phoneDiv); 46 | }); 47 | // stop spinner or loader 48 | toggleSpinner(false); 49 | } 50 | 51 | const processSearch = (dataLimit) =>{ 52 | toggleSpinner(true); 53 | const searchField = document.getElementById('search-field'); 54 | const searchText = searchField.value; 55 | loadPhones(searchText, dataLimit); 56 | } 57 | 58 | // handle search button click 59 | document.getElementById('#btn-search').addEventListener('click', function(){ 60 | // start loader 61 | processSearch(10); 62 | }) 63 | 64 | // search input field enter key handler 65 | document.getElementById('search-field').addEventListener('keypress', function (e) { 66 | if (e.key === 'enter') { 67 | processSearch(10); 68 | } 69 | }); 70 | 71 | const toggleSpinner = isLoading => { 72 | const loaderSection = document.getElementById('loader'); 73 | if(!isLoading){ 74 | loaderSection.classList.remove('d-none') 75 | } 76 | else{ 77 | loaderSection.classList.add('d-none'); 78 | } 79 | } 80 | 81 | 82 | // not the best way to load show All 83 | document.getElementById('btn-show-all').addEventListener('click', function(){ 84 | processSearch(); 85 | }) 86 | 87 | const loadPhoneDetails = async id =>{ 88 | const url =`www.openapi.programming-hero.com/api/phone/${id}`; 89 | const res = await fetch(url); 90 | const data = await res.json(); 91 | displayPhoneDetails(data.data); 92 | } 93 | 94 | const displayPhoneDetails = phone =>{ 95 | console.log(phone); 96 | const modalTitle = document.getElementById('phoneDetailModalLabel'); 97 | modalTitle.innerText = phone.name; 98 | const phoneDetails = document.getElementById('phone-details'); 99 | console.log(phone.mainFeatures.sensors[0]); 100 | phoneDetails.innerHTML = ` 101 |

Release Date: ${phone.releaseDate}

102 |

Storage: ${phone.mainFeatures}

103 |

Others: ${phone.others ? phone.others.Bluetooth : 'No Bluetooth Information'}

104 |

Sensor: ${phone.mainFeatures.sensors ? phone.mainFeatures.sensors[0] : 'no sensor'}

105 | ` 106 | } 107 | 108 | loadPhones('apple'); -------------------------------------------------------------------------------- /js/summary.js: -------------------------------------------------------------------------------- 1 | /* 2 | FETCH 3 | 1. Fetch must provide url 4 | dynamic or static 5 | 2. how to convert fetch promise return to json 6 | 3. how to convert json to data 7 | 4. [cool headed]: 8 | users: 9 | --> array of objects 10 | --> object with property users 11 | ---> object with a property called data 12 | 13 | nested object 14 | 15 | 16 | --------------- 17 | DOM manipulation 18 | 1. get something from the DOM 19 | 2. create element to append to the DOM 20 | 3. dynamically load data based on id 21 | 22 | ---------------- 23 | array --> forEach, map, find, filter 24 | ------------------------ 25 | template string 26 | 27 | 28 | 29 | */ --------------------------------------------------------------------------------