{"id":18947459,"url":"https://github.com/cholis04/tip-calculator-app","last_synced_at":"2026-04-14T15:32:13.543Z","repository":{"id":51298618,"uuid":"465707533","full_name":"cholis04/tip-calculator-app","owner":"cholis04","description":"This is my solution to the Tip Calculator App challenge on Frontend Mentor.","archived":false,"fork":false,"pushed_at":"2022-08-02T04:50:06.000Z","size":14950,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-06-01T22:12:54.114Z","etag":null,"topics":["accessibility","calculator","calculator-application","frontend","frontend-mentor","javascript","nextjs","styled-components"],"latest_commit_sha":null,"homepage":"https://tip-calculator-app-one-rho.vercel.app/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cholis04.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-03-03T12:21:31.000Z","updated_at":"2022-05-07T04:41:25.000Z","dependencies_parsed_at":"2022-09-25T03:24:28.604Z","dependency_job_id":null,"html_url":"https://github.com/cholis04/tip-calculator-app","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/cholis04/tip-calculator-app","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cholis04%2Ftip-calculator-app","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cholis04%2Ftip-calculator-app/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cholis04%2Ftip-calculator-app/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cholis04%2Ftip-calculator-app/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cholis04","download_url":"https://codeload.github.com/cholis04/tip-calculator-app/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cholis04%2Ftip-calculator-app/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31803247,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-14T11:13:53.975Z","status":"ssl_error","status_checked_at":"2026-04-14T11:13:53.299Z","response_time":153,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["accessibility","calculator","calculator-application","frontend","frontend-mentor","javascript","nextjs","styled-components"],"created_at":"2024-11-08T13:10:01.541Z","updated_at":"2026-04-14T15:32:13.518Z","avatar_url":"https://github.com/cholis04.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Frontend Mentor - Tip calculator app solution\n\nThis is a solution to the [Tip calculator app challenge on Frontend Mentor](https://www.frontendmentor.io/challenges/tip-calculator-app-ugJNGbJUX). Frontend Mentor challenges help you improve your coding skills by building realistic projects.\n\n## Table of contents\n\n- [Overview](#overview)\n  - [The challenge](#the-challenge)\n  - [Screenshot](#screenshot)\n  - [Links](#links)\n- [My process](#my-process)\n  - [Built with](#built-with)\n  - [What I learned](#what-i-learned)\n    - [Format Number as Currency](#format-number-as-currency)\n    - [Icon inside an Input Element](#icon-inside-an-input-element)\n  - [Continued development](#continued-development)\n    - [Remove Leading Zero](#remove-leading-zero)\n    - [Prevent characters other than numbers](#prevent-characters-other-than-numbers)\n    - [Maximum Value for Tip and Number of people](#maximum-value-for-tip-and-number-of-people)\n    - [Auto tick when have same value on manual tip](#auto-tick-when-have-same-value-on-manual-tip)\n    - [Amount to Exponential when the result is much larger](#amount-to-exponential-when-the-result-is-much-larger)\n  - [Useful resources](#useful-resources)\n- [Author](#author)\n- [Acknowledgments](#acknowledgments)\n\n## Overview\n\n### The challenge\n\nUsers should be able to:\n\n- View the optimal layout for the app depending on their device's screen size\n- See hover states for all interactive elements on the page\n- Calculate the correct tip and total cost of the bill per person\n\n### Screenshot\n\n![Preview App](./screenshots/Frontend_Mentor_tip_calculator_app_preview.gif)\n\n### Links\n\n- Live Site URL: [https://tip-calculator-app-one-rho.vercel.app/](https://tip-calculator-app-one-rho.vercel.app/)\n\n## My process\n\n### Built with\n\n- Semantic HTML5 markup\n- CSS custom properties\n- Flexbox\n- CSS Grid\n- [React](https://reactjs.org/) - JS library\n- [Next.js](https://nextjs.org/) - React framework\n- [Styled Components](https://styled-components.com/) - For styles\n- [Fontsource](https://fontsource.org/) - Self-host Open Source fonts\n- [JEST](https://jestjs.io/) - For testing\n\n### What I learned\n\n#### Format Number as Currency\n\nDisplays the calculation results in the form of currency. Create a currency format by using the built-in function **Intl.NumberFormat**.\n\n```js\nconst formatCurrency = (amount: number) =\u003e {\n  const formater = new Intl.NumberFormat('en-US', {\n    style: 'currency',\n    currency: 'USD',\n    minimumFractionDigits: 2,\n  });\n  return formater.format(amount);\n};\n```\n\n#### Icon inside an Input Element\n\nWithout having to add any extra elements, I gave the icon the text itself. By adding **background-image** property in css. Then set the position of the icon to match by using the **background-position** property.\n\n```css\n.input-text {\n  background-image: url('./icon-dollar.svg');\n  background-repeat: no-repeat;\n  background-position: 0.6em 50%;\n\n  /* Icon Area */\n  padding-left: 1.8em;\n}\n```\n\n### Continued development\n\n#### Remove Leading Zero\n\n![Remove Leading Zero](./screenshots/Frontend_Mentor_Tip_calculator_app_Remove_Leading_Zero.gif)\n\nThe leading 0 has **no effect** on the calculation at all. And the number of leading 0's can sometimes be confusing. I prefer to **automatically eliminate** the number if it is in front of other numbers.\n\nI did a pattern matching **regex** that contains leading 0. Then replace it with empty text.\n\n```js\nif (/^0+/.test(value)) {\n  e.currentTarget.value = value.replace(/^0+/, '');\n}\n```\n\n#### Prevent characters other than numbers\n\nOn the input element of the number type. User can enter characters like e, +, -. To avoid unwanted errors. I prevent users from doing that. I put a function on the **onKeyPress** attribute.\n\n```js\nconst preventKeyPress = (e: React.KeyboardEvent\u003cHTMLInputElement\u003e) =\u003e {\n  if (e.key === '-' || e.key === 'e' || e.key === '+' || e.key === ',') {\n    e.preventDefault();\n  }\n\n  // Prevent char . on first type\n  if (e.currentTarget.value === '' || e.currentTarget.valueAsNumber === 0) {\n    if (e.key === '.') {\n      e.preventDefault();\n    }\n  }\n};\n```\n\n#### Maximum Value for Tip and Number of people\n\nSo that the calculations are not too many and become **infinity**, I limit the input that the user can make.\n\n```js\n\u003cInputText max={maximum} /\u003e\n```\n\n#### Auto tick when have same value on manual tip\n\n![Auto Tick](./screenshots/Frontend_Mentor_Tip_calculator_app_Auto_Checked.gif)\n\nIf the **user's custom input** has the same value as **the registered radio button**. Then the custom input will be **removed** and the Radio button having the same value will be **checked automatically**.\n\n```js\n// Empty Custom input if has a same value\nconst handleBlur = (e: React.FormEvent\u003cHTMLInputElement\u003e) =\u003e {\n  const value = e.currentTarget.value;\n  if (\n    value === '5' ||\n    value === '10' ||\n    value === '15' ||\n    value === '25' ||\n    value === '50'\n  ) {\n    if (inputCustomRef.current !== null) {\n      inputCustomRef.current.value = '';\n    }\n    setValue(id, value);\n  }\n};\n```\n\n#### Amount to Exponential when the result is much larger\n\n![Amount to Exponential](./screenshots/Frontend_Mentor_Tip_calculator_app_Exponential.gif)\n\nSame as before. So that the results of the calculations are not **too long** and become **infinity** which causes the display to be damaged. So when the calculation value exceeds a certain limit it will be displayed in **exponential form**.\n\nBut the user can still see the complete calculation result on the **title** attribute.\n\n```js\n\u003cTotalAmount title={`${titleComponent} / person : ${formatCurrency(amount)}`}\u003e\n  {amount \u003e= 999999 ? '$' + amount.toExponential(4) : formatCurrency(amount)}\n\u003c/TotalAmount\u003e\n```\n\n### Useful resources\n\n- [https://www.w3.org/TR/2016/WD-wai-aria-practices-1.1-20160317/examples/radio/radio.html](https://www.w3.org/TR/2016/WD-wai-aria-practices-1.1-20160317/examples/radio/radio.html)\n- [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat)\n- [https://masteringjs.io/tutorials/fundamentals/trim-leading-zeros](https://masteringjs.io/tutorials/fundamentals/trim-leading-zeros)\n- [https://www.w3schools.com/jsref/jsref_toexponential.asp](https://www.w3schools.com/jsref/jsref_toexponential.asp)\n\n## Author\n\n- Website - [https://cholis04.github.io](https://cholis04.github.io)\n- Frontend Mentor - [@cholis04](https://www.frontendmentor.io/profile/cholis04)\n- Dribbble - [cholis04](https://dribbble.com/cholis04)\n- Instagram - [@cholis04](https://instagram.com/cholis04)\n- Codepen - [cholis04](https://codepen.io/cholis04)\n\n## Acknowledgments\n\nMany thanks to anyone who provided feedback.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcholis04%2Ftip-calculator-app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcholis04%2Ftip-calculator-app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcholis04%2Ftip-calculator-app/lists"}