Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR to add JavaScript ToDo app #1

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# ui-playground
Playground repo for ui training

Playground repo for ui training
170 changes: 170 additions & 0 deletions debarshi/css/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
@import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;500&display=swap");

:root {
--primary-color: #f25278;
--secondary-color: rgb(69, 69, 236);
--text-primary: #fff;
--border-color: #bdbdbd;
--disabled-color: rgba(189, 189, 235, 0.925);
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: "Open Sans", "Courier New", Courier, monospace;
}

body {
min-height: calc(100vh - 1.5rem);
width: 100%;
background-color: var(--primary-color);
}

body li {
list-style-type: none;
}

.header-text {
width: 100%;
text-align: center;
margin: 1.5rem 0;
color: var(--text-primary);
}
.container {
margin: 0 auto;
max-width: 35rem;
}

.input-container {
margin: 1rem auto;
display: flex;
background-color: var(--text-primary);
align-items: center;
}
.input-container > input {
padding: 0.5rem 0.8rem;
width: 100%;
outline: none;
font-size: 1.15rem;
border: 0;
}
.input-container > button {
padding-right: 1rem;
background: transparent;
border: 0;
color: var(--secondary-color);
font-weight: 600;
font-size: 1.05rem;
cursor: pointer;
}

.input-container button:disabled,
.todo-container button:disabled {
color: var(--disabled-color);
cursor: initial;
}

.todo-container {
background-color: var(--text-primary);
margin: 1.5rem auto;
}

.todo-container button {
min-width: 1.5rem;
height: 1.5rem;
margin-right: 8px;
background-color: var(--primary-color);
color: var(--text-primary);
border: 0;
outline: none;
cursor: pointer;
font-weight: 600;
}

.todo {
display: flex;
width: 100%;
align-items: center;
position: relative;
padding: 1rem 0;
border-bottom: 1px solid var(--border-color);
}

.todo.sub-todo-input {
padding-top: 1rem;
padding-left: 1.2rem;
}

button {
padding: 0 10px;
}
.todo button:disabled {
opacity: 0.8;
color: var(--text-primary);
cursor: initial;
}
.todo input[type="checkbox"] {
margin-right: 8px;
cursor: pointer;
}
.todo input[type="text"] {
padding: 0.4rem;
flex: 1;
outline: none;
}
.todo p {
font-size: 1.05rem;
flex: 1;
word-break: break-all;
color: gray;
margin-bottom: 4px;
text-align: start;
padding: 0 8px;
}

p.text-through {
text-decoration: line-through;
color: var(--primary-color);
}

.sub-todo {
padding-left: 1.2rem;
}

.action-container {
display: flex;
justify-content: end;
align-items: center;
margin: 1rem 0 1rem auto;
}

/* Utility classes */
.d-none {
display: none;
}

.d-block {
display: block;
}
.padding-xs {
padding: 1rem;
}

.action-container .action-btn {
display: block;
padding: 0 1rem;
margin: 0;
}
.action-container .action-btn:first-child {
margin-right: 8px;
}
.invisible {
visibility: hidden;
}
.padding-bottom-0 {
padding-bottom: 0;
}

.padding-top-0 {
padding-top: 0;
}
37 changes: 37 additions & 0 deletions debarshi/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="css/style.css" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.10.1/css/all.min.css"
integrity="sha512-9my9Mb2+0YO+I4PUCSwUYO7sEK21Y0STBAiFEYoWtd2VzLEZZ4QARDrZ30hdM1GlioHJ8o8cWQiy8IAb1hy/Hg=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
/>
<title>FlixTodos</title>
</head>
<body>
<main>
<h2 class="header-text">TO-DO LIST</h2>
<div class="container input-container">
<input type="text" placeholder="New Task" />
<button type="button" disabled id="add-todo">ADD</button>
</div>
<div class="container todo-container d-none">
<div id="todo-wrapper"></div>
<div class="action-container">
<button id="mark-complete" class="action-btn">
Mark All Complete
</button>
<button id="clear" class="action-btn">Delete All</button>
</div>
</div>
<h3 class="header-text" id="no-todo-text">No Todos found</h3>
</main>
<script type="module" src="./js/todo.js"></script>
</body>
</html>
5 changes: 5 additions & 0 deletions debarshi/js/components/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export { default as createTodoBase } from "./todoBase.js"
export { default as createTodoRoot } from "./todoRoot.js"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should use semicolon after every statement. Applies to all the files.

export { default as createTodoInput } from "./todoInput.js"
export { default as createTodoCheckbox } from "./todoCheckbox.js"
export { default as createTodoButton } from "./todoButton.js"
55 changes: 55 additions & 0 deletions debarshi/js/components/todoBase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import todos from "../constant.js"
import render from "../todo.js"
import { todoWrapper } from "../selectors.js"

const createTodoBase = (todo, props = {}) => {
const { draggable = false } = props

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should use semicolons after every statement


const onTodoDragStart = (event) => {
const dataId = event.currentTarget.getAttribute("data-id")
event.dataTransfer.dropEffect = "move"
event.dataTransfer.setData("data_id", dataId)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

two different variable with same name but different convention would be confusing - data-id and data_id

}

const onTodoDragOver = (event) => {
event.preventDefault()
}

const onTodoDrop = (event) => {
const currentId = event.currentTarget.getAttribute("data-id")
const previousId = event.dataTransfer.getData("data_id")

const currentTodoIdx = todos.findIndex(
(todo) => todo.id === Number(currentId),
)
const previousTodoIdx = todos.findIndex(
(todo) => todo.id === Number(previousId),
)

if (currentTodoIdx >= 0 && previousTodoIdx >= 0) {
const temp = todos[currentTodoIdx]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can use destructing assignment here for swapping to avoid temp - Eg: [b,a] = [a,b]

todos[currentTodoIdx] = todos[previousTodoIdx]
todos[previousTodoIdx] = temp

todoWrapper.innerHTML = ""
render()
}
}

const todoRootEl = document.createElement("li")
todoRootEl.setAttribute("draggable", draggable)

if (todo?.id) {
todoRootEl.setAttribute("data-id", todo?.id)
}

if (draggable) {
todoRootEl.addEventListener("dragstart", onTodoDragStart)
todoRootEl.addEventListener("dragover", onTodoDragOver)
todoRootEl.addEventListener("drop", onTodoDrop)
}

return todoRootEl
}

export default createTodoBase
14 changes: 14 additions & 0 deletions debarshi/js/components/todoButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const createTodoButton = (props = {}) => {
const { textContent = "", innerHTML = "" } = props

const todoBtnEl = document.createElement("button")
todoBtnEl.textContent = textContent

if (innerHTML) {
todoBtnEl.innerHTML = innerHTML
}

return todoBtnEl
}

export default createTodoButton
9 changes: 9 additions & 0 deletions debarshi/js/components/todoCheckbox.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const createTodoCheckbox = (isCompleted = false) => {
const todoCheckEl = document.createElement("input")
todoCheckEl.type = "checkbox"
todoCheckEl.checked = isCompleted

return todoCheckEl
}

export default createTodoCheckbox
11 changes: 11 additions & 0 deletions debarshi/js/components/todoInput.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const createTodoInput = (props = {}) => {
const { type = "text", value = "" } = props

const inputEl = document.createElement("input")
inputEl.type = type
inputEl.value = value

return inputEl
}

export default createTodoInput
31 changes: 31 additions & 0 deletions debarshi/js/components/todoRoot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const createTodoRoot = (hasChildTodos = false) => {
function onTodoMouseOver() {
this.childNodes.forEach((node) => {
if (node.id === "sub-todo") {
node.classList.remove("invisible")
}
})
}

function onTodoMouseLeave() {
this.childNodes.forEach((node) => {
if (node.id === "sub-todo") {
node.classList.add("invisible")
}
})
}

const todoEl = document.createElement("div")
todoEl.classList.add("todo")

if (hasChildTodos) {
todoEl.addEventListener("mouseover", onTodoMouseOver)
todoEl.addEventListener("mouseleave", onTodoMouseLeave)
} else {
todoEl.classList.add("sub-todo")
}

return todoEl
}

export default createTodoRoot
3 changes: 3 additions & 0 deletions debarshi/js/constant.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const todos = []

export default todos
17 changes: 17 additions & 0 deletions debarshi/js/selectors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const mainEl = document.querySelector("main")
const inputEl = document.querySelector("input")
const cardContainer = document.querySelector(".todo-container")
const todoWrapper = document.querySelector("#todo-wrapper")
const addTodoBtn = document.querySelector(".input-container button")
const noTodoText = document.querySelector("#no-todo-text")
const markAllCompleteBtn = document.querySelector("#mark-complete")

export {
inputEl,
cardContainer,
todoWrapper,
addTodoBtn,
noTodoText,
markAllCompleteBtn,
mainEl,
}
Loading