Skip to content

Instantly share code, notes, and snippets.

@nicobytes
Last active April 21, 2025 14:46
Show Gist options
  • Save nicobytes/ba2252b0b5ac2cbdafc40c0accd24862 to your computer and use it in GitHub Desktop.
Save nicobytes/ba2252b0b5ac2cbdafc40c0accd24862 to your computer and use it in GitHub Desktop.
Angular Course

Angular Todo App

styles.css
html,
body {
  margin: 0;
  padding: 0;
}

button {
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font-size: 100%;
  vertical-align: baseline;
  font-family: inherit;
  font-weight: inherit;
  color: inherit;
  -webkit-appearance: none;
  appearance: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  font-family: "Roboto", sans-serif;
  background: #f5f5f5;
  color: #111111;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-weight: 300;
}

:focus {
  outline: 0;
}
home.component.css
.container {
  min-width: 230px;
  max-width: 550px;
  margin: 0 auto;
}

.header {
  background-image: linear-gradient(
    224deg,
    hsl(240deg 100% 50%) 2%,
    hsl(249deg 100% 59%) 63%,
    hsl(252deg 99% 64%) 78%,
    hsl(253deg 98% 68%) 87%,
    hsl(254deg 96% 73%) 92%,
    hsl(253deg 93% 77%) 96%,
    hsl(251deg 89% 81%) 98%,
    hsl(246deg 81% 85%) 99%,
    hsl(232deg 68% 88%) 100%,
    hsl(200deg 53% 90%) 100%
  );
  padding-bottom: 4rem;
}

.hidden {
  display: none;
}

.todoapp-wrapper {
  position: relative;
  top: -40px;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
  overflow: hidden;
}

.todoapp input::-webkit-input-placeholder {
  font-style: italic;
  font-weight: 400;
  color: rgba(0, 0, 0, 0.4);
}

.todoapp input::-moz-placeholder {
  font-style: italic;
  font-weight: 400;
  color: rgba(0, 0, 0, 0.4);
}

.todoapp input::input-placeholder {
  font-style: italic;
  font-weight: 400;
  color: rgba(0, 0, 0, 0.4);
}

.header h1 {
  width: 100%;
  font-size: 3rem;
  font-weight: 200;
  color: white;
  padding-top: 2rem;
  margin: 0;
}

.header h1 + p {
  margin: 0;
  color: white;
  padding-bottom: 1.2rem;
}

.new-todo,
.edit {
  position: relative;
  margin: 0;
  width: 100%;
  font-size: 24px;
  font-family: inherit;
  font-weight: inherit;
  line-height: 1.4em;
  color: inherit;
  padding: 6px;
  border: 1px solid #999;
  box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
  box-sizing: border-box;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.new-todo {
  padding: 2rem;
  height: 65px;
  border: none;
  background: white;
  box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03);
  border-radius: 8px;
}

.main {
  position: relative;
  z-index: 2;
  border-top: 1px solid #e6e6e6;
}

.toggle-all {
  width: 1px;
  height: 1px;
  border: none;
  /* Mobile Safari */
  opacity: 0;
  position: absolute;
  right: 100%;
  bottom: 100%;
}

.toggle-all + label {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 45px;
  height: 65px;
  font-size: 0;
  position: absolute;
  top: -65px;
  left: -0;
}

.toggle-all + label:before {
  content: "❯";
  display: inline-block;
  font-size: 22px;
  color: #949494;
  padding: 10px 27px 10px 27px;
  -webkit-transform: rotate(90deg);
  transform: rotate(90deg);
}

.toggle-all:checked + label:before {
  color: #484848;
}

.todo-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.todo-list li {
  position: relative;
  font-size: 24px;
  border-bottom: 1px solid #ededed;
  padding: 0rem 1rem;
}

.todo-list li:last-child {
  border-bottom: none;
}

.todo-list li.editing {
  border-bottom: none;
  padding: 0;
}

.todo-list li.editing .edit {
  display: block;
  width: calc(100% - 4rem);
  padding: 12px 16px;
  margin: 0 0 0 4rem;
}

.todo-list li.editing .view {
  display: none;
}

.todo-list li .toggle {
  text-align: center;
  width: 40px;
  /* auto, since non-WebKit browsers doesn't support input styling */
  height: auto;
  position: absolute;
  top: 0;
  bottom: 0;
  margin: auto 0;
  border: none;
  /* Mobile Safari */
  -webkit-appearance: none;
  appearance: none;
}

.todo-list li .toggle {
  opacity: 0;
}

.todo-list li .toggle + label {
  /*
		Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433
		IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/
	*/
  background-image: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23949494%22%20stroke-width%3D%223%22/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center left;
}

.todo-list li .toggle:checked + label {
  background-image: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%2359A193%22%20stroke-width%3D%223%22%2F%3E%3Cpath%20fill%3D%22%233EA390%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22%2F%3E%3C%2Fsvg%3E");
}

.todo-list li label {
  word-break: break-all;
  padding: 15px 15px 15px 60px;
  display: block;
  line-height: 1.2;
  transition: color 0.4s;
  font-weight: 400;
  color: #484848;
}

.todo-list li.completed label {
  color: #949494;
  text-decoration: line-through;
}

.todo-list li .destroy {
  display: none;
  position: absolute;
  top: 0;
  right: 10px;
  bottom: 0;
  width: 40px;
  height: 40px;
  margin: auto 0;
  font-size: 30px;
  color: #949494;
  transition: color 0.2s ease-out;
}

.todo-list li .destroy:hover,
.todo-list li .destroy:focus {
  color: #c18585;
}

.todo-list li .destroy:after {
  content: "×";
  display: block;
  height: 100%;
  line-height: 1.1;
}

.todo-list li:hover .destroy {
  display: block;
}

.todo-list li .edit {
  display: none;
}

.todo-list li.editing:last-child {
  margin-bottom: -1px;
}

.footer {
  padding: 1rem 1.5rem;
  height: 20px;
  text-align: center;
  font-size: 15px;
  border-top: 1px solid #e6e6e6;
}

.todo-count {
  float: left;
  text-align: left;
}

.todo-count strong {
  font-weight: 300;
}

.filters {
  margin: 0;
  padding: 0;
  list-style: none;
  position: absolute;
  right: 0;
  left: 0;
}

.filters li {
  display: inline;
}

.filters li a {
  color: inherit;
  margin: 3px;
  padding: 3px 7px;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: 3px;
}

.filters li a:hover {
  border-color: #6e49fe;
}

.filters li a.selected {
  border-color: #4c33b1;
}

.clear-completed,
html .clear-completed:active {
  float: right;
  position: relative;
  line-height: 19px;
  text-decoration: none;
  cursor: pointer;
}

.clear-completed:hover {
  text-decoration: underline;
}

.info {
  margin: 65px auto 0;
  color: #4d4d4d;
  font-size: 11px;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
  text-align: center;
}

.info p {
  line-height: 1;
}

.info a {
  color: inherit;
  text-decoration: none;
  font-weight: 400;
}

.info a:hover {
  text-decoration: underline;
}

/*
	Hack to remove background from Mobile Safari.
	Can't use it globally since it destroys checkboxes in Firefox
*/
@media screen and (-webkit-min-device-pixel-ratio: 0) {
  .toggle-all,
  .todo-list li .toggle {
    background: none;
  }

  .todo-list li .toggle {
    height: 40px;
  }
}

@media (max-width: 430px) {
  .footer {
    height: 50px;
  }

  .filters {
    bottom: 10px;
  }
}
home.component.html
<section class="todoapp">
  <header class="header">
    <div class="container">
      <h1>My Day</h1>
      <p>All my tasks in one place</p>
      <input
        class="new-todo"
        placeholder="Type new todo"
        autofocus
        type="text"
      />
    </div>
  </header>
  <div class="container todoapp-wrapper">
    <!-- This section should be hidden by default and shown when there are todos -->
    <section class="main">
      <ul class="todo-list">
        <li class="completed">
          <div class="view">
            <input class="toggle" type="checkbox" checked />
            <label>Learn JavaScript</label>
            <button class="destroy"></button>
          </div>
          <input class="edit" value="Learn JavaScript" />
        </li>
        <li>
          <div class="view">
            <input class="toggle" type="checkbox" />
            <label>Buy a unicorn</label>
            <button class="destroy"></button>
          </div>
          <input class="edit" value="Buy a unicorn" />
        </li>
        <li class="editing">
          <div class="view">
            <input class="toggle" type="checkbox" />
            <label>Make dishes</label>
            <button class="destroy"></button>
          </div>
          <input class="edit" value="Make dishes" />
        </li>
      </ul>
    </section>
    <!-- This footer should be hidden by default and shown when there are todos -->
    <footer class="footer">
      <!-- This should be `0 items left` by default -->
      <span class="todo-count"><strong>0</strong> item left</span>
      <!-- Remove this if you don't implement routing -->
      <ul class="filters">
        <li>
          <a routerLink="/" class="selected">All</a>
        </li>
        <li>
          <a routerLink="/pending">Pending</a>
        </li>
        <li>
          <a routerLink="/completed">Completed</a>
        </li>
      </ul>
      <!-- Hidden if no completed items are left ↓ -->
      <button class="clear-completed">Clear completed</button>
    </footer>
  </div>
</section>

Product

<div class="group rounded-lg border">
    <a href="#" class="w-full overflow-hidden rounded-t-lg bg-gray-200">
        <img [src]="image" [alt]="title" class="h-full w-full object-cover object-center group-hover:opacity-75">
    </a>
    <div class="flex flex-col space-y-2 p-4">
        <h3 class="text-sm text-gray-700">{{ title }}</h3>
        <p class="text-lg font-medium text-gray-900">{{price}}</p>
        <button class="text-black bg-gray-200 font-medium rounded-lg text-sm px-5 py-2.5 w-full"
            (click)="addToCartHandler()">Add to cart</button>
    </div>
</div>

Header

<nav>
  <div
    class="max-w-screen-xl flex flex-wrap items-center justify-between mx-auto p-4"
  >
    <div class="flex items-center space-x-8">
      <a href="https://flowbite.com/" class="flex items-center ">
        <img
          src="https://flowbite.com/docs/images/logo.svg"
          class="h-6 mr-3"
          alt="Flowbite Logo"
        />
        <span class="self-center text-xl font-semibold whitespace-nowrap"
          >Flowbite</span
        >
      </a>
      <ul class="flex space-x-6">
        <li>
          <a
            href="#"
            class="block underline hover:underline"
            aria-current="page"
            >Home</a
          >
        </li>
        <li>
          <a
            href="#"
            class="block hover:underline"
            >About</a
          >
        </li>
        <li>
          <a
            href="#"
            class="block hover:underline"
            >Services</a
          >
        </li>
      </ul>
    </div>
    <div class="flex items-center">
      <button class="px-4">
        <svg
          xmlns="http://www.w3.org/2000/svg"
          fill="none"
          viewBox="0 0 24 24"
          stroke-width="1.5"
          stroke="currentColor"
          class="w-6 h-6"
        >
          <path
            stroke-linecap="round"
            stroke-linejoin="round"
            d="M2.25 3h1.386c.51 0 .955.343 1.087.835l.383 1.437M7.5 14.25a3 3 0 00-3 3h15.75m-12.75-3h11.218c1.121-2.3 2.1-4.684 2.924-7.138a60.114 60.114 0 00-16.536-1.84M7.5 14.25L5.106 5.272M6 20.25a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm12.75 0a.75.75 0 11-1.5 0 .75.75 0 011.5 0z"
          />
        </svg>
      </button>
    </div>
  </div>
</nav>

Cart

<div
  class="fixed border-l-4 top-0 right-0 bg-red z-40 w-72 h-screen p-4 overflow-y-auto transition-transform bg-white translate-x-full"
>
  <div class="flex justify-between items-center">
    <p class="text-xl">My Cart</p>
    <button>
      <svg
        xmlns="http://www.w3.org/2000/svg"
        fill="none"
        viewBox="0 0 24 24"
        stroke-width="1.5"
        stroke="currentColor"
        class="w-6 h-6"
      >
        <path
          stroke-linecap="round"
          stroke-linejoin="round"
          d="M6 18L18 6M6 6l12 12"
        />
      </svg>
    </button>
  </div>
</div>

404

<section class="bg-white h-screen w-screen p-10">
  <div class="py-8 px-4 mx-auto">
      <div class="mx-auto max-w-screen-sm text-center">
          <h1 class="mb-4 text-7xl tracking-tight font-extrabold lg:text-9xl text-primary-600 ">404</h1>
          <p class="mb-4 text-3xl tracking-tight font-bold text-gray-900 md:text-4xl ">Something's missing.</p>
          <p class="mb-4 text-lg font-light text-gray-500 ">Sorry, we can't find that page. You'll find lots to explore on the home page. </p>
          <a href="#" class="inline-flex bg-blue-600 text-white hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blues-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center my-4">Back to Homepage</a>
      </div>
  </div>
</section>

Detalle de producto

<div class="w-full flex space-x-10">
  <div class="flex flex-col w-1/3">
    <div class="w-full rounded border border-gray-200">
      <img
        alt="ecommerce"
        class="w-full object-cover object-center"
        src="https://www.whitmorerarebooks.com/pictures/medium/2465.jpg"
      />
    </div>
    <div class="flex items-center justify-center mt-1">
      <div class="grid grid-cols-3 gap-1">
        <img
          alt="ecommerce"
          class="object-cover object-center rounded border-2 border-gray-200"
          src="https://www.whitmorerarebooks.com/pictures/medium/2465.jpg"
        />
        <img
          alt="ecommerce"
          class="w-full object-cover object-center rounded border-2 border-gray-200"
          src="https://www.whitmorerarebooks.com/pictures/medium/2465.jpg"
        />
        <img
          alt="ecommerce"
          class="w-full object-cover object-center rounded border-2 border-gray-200"
          src="https://www.whitmorerarebooks.com/pictures/medium/2465.jpg"
        />
      </div>
    </div>
  </div>
  <div class="mt-5 w-full">
    <h2 class="text-sm title-font text-gray-500 tracking-widest">BRAND NAME</h2>
    <h1 class="text-gray-900 text-3xl title-font font-medium mb-1">
      The Catcher in the Rye
    </h1>
    <p class="leading-relaxed">
      Fam locavore kickstarter distillery. Mixtape chillwave tumeric sriracha
      taximy chia microdosing tilde DIY. XOXO fam indxgo juiceramps cornhole raw
      denim forage brooklyn. Everyday carry +1 seitan poutine tumeric. Gastropub
      blue bottle austin listicle pour-over, neutra jean shorts keytar banjo
      tattooed umami cardigan.
    </p>
    <p class="title-font font-medium text-2xl text-gray-900 mt-5">$58.00</p>
    <button
      class="flex text-white bg-red-500 border-0 py-2 px-6 focus:outline-none hover:bg-red-600 rounded"
    >
      Add To Cart
    </button>
  </div>
</div>
@andydev29
Copy link

Very useful for the course, thanks a lot!

@juandgo
Copy link

juandgo commented Apr 14, 2025

This is great and very handy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment