Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
T
Todo-Storybook
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Madhankumar
Todo-Storybook
Commits
98006a02
Commit
98006a02
authored
Sep 26, 2023
by
Madhankumar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
auto height textarea and loading
parent
a3281ff0
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
122 additions
and
105 deletions
+122
-105
db.json
db.json
+7
-36
index.js
src/app-context/index.js
+12
-4
layout.css
src/components/base/layout/layout.css
+6
-1
index.js
src/components/top-level/task/index.js
+62
-34
task.css
src/components/top-level/task/task.css
+12
-16
tasks.css
src/components/top-level/tasks/tasks.css
+3
-0
api.js
src/lib/api.js
+3
-4
index.js
src/pages/index.js
+17
-10
No files found.
db.json
View file @
98006a02
{
"task"
:
[
{
"title"
:
"
This HTML file is a template.
"
,
"title"
:
"
Buy a tomato
"
,
"isCompleted"
:
false
,
"id"
:
2
},
{
"title"
:
"This HTML file is a template. "
,
"isCompleted"
:
true
,
"id"
:
4
},
{
"title"
:
"hello"
,
"isCompleted"
:
false
,
"id"
:
5
},
{
"title"
:
"cscdcv"
,
"isCompleted"
:
false
,
"id"
:
6
"id"
:
1
},
{
"title"
:
"
vdvdcv
"
,
"title"
:
"
Go to office
"
,
"isCompleted"
:
false
,
"id"
:
7
},
{
"title"
:
"vdvdv"
,
"isCompleted"
:
false
,
"id"
:
8
},
{
"title"
:
"ddvdvd"
,
"isCompleted"
:
true
,
"id"
:
9
},
{
"title"
:
"dvdvdvd"
,
"isCompleted"
:
false
,
"id"
:
10
"id"
:
2
},
{
"title"
:
"
wwww
"
,
"title"
:
"
Party time
"
,
"isCompleted"
:
false
,
"id"
:
11
"id"
:
3
}
]
}
\ No newline at end of file
src/app-context/index.js
View file @
98006a02
...
...
@@ -6,7 +6,7 @@ export const useAppContext = () => useContext(TodoContext);
export
function
TodoProvider
({
children
})
{
const
[
todo
,
setTodo
]
=
useState
([]);
const
[
loading
,
setLoading
]
=
useState
(
false
);
//POST METHOD
async
function
addTodo
({
title
})
{
try
{
...
...
@@ -21,7 +21,11 @@ export function TodoProvider({ children }) {
async
function
updateTodo
({
id
,
title
,
isCompleted
})
{
try
{
const
response
=
await
api
.
updateTodo
({
id
,
title
,
isCompleted
});
setTodo
(
response
);
// const index = todo.map((item) => item.id).indexOf(id);
// todo.splice(index, 1, { id, title, isCompleted });
const
data
=
await
response
.
json
();
setTodo
(
todo
.
map
((
e
)
=>
(
e
.
id
===
id
?
data
:
e
)));
}
catch
(
err
)
{
toast
.
error
(
err
.
message
);
}
...
...
@@ -32,6 +36,8 @@ export function TodoProvider({ children }) {
try
{
const
response
=
await
api
.
getTodos
();
setTodo
(
response
);
setLoading
(
true
);
return
response
;
}
catch
(
err
)
{
toast
.
error
(
err
.
message
);
}
...
...
@@ -40,8 +46,9 @@ export function TodoProvider({ children }) {
//DELETE METHOD
async
function
deleteTodo
(
id
)
{
try
{
const
response
=
await
api
.
deleteTodo
(
id
);
setTodo
(
response
);
await
api
.
deleteTodo
(
id
);
setTodo
(
todo
.
filter
((
e
)
=>
e
.
id
!==
id
));
}
catch
(
err
)
{
toast
.
error
(
err
.
message
);
}
...
...
@@ -49,6 +56,7 @@ export function TodoProvider({ children }) {
const
value
=
{
todo
,
loading
,
addTodo
,
getTodos
,
deleteTodo
,
...
...
src/components/base/layout/layout.css
View file @
98006a02
.container
{
box-shadow
:
rgba
(
0
,
0
,
0
,
0.09
)
0px
3px
12px
;
background
:
white
;
min-height
:
40vh
;
}
.container
h2
{
box-shadow
:
rgba
(
0
,
0
,
0
,
0.08
)
0px
3px
5px
;
...
...
@@ -10,6 +9,12 @@
padding
:
1.3rem
0px
;
margin
:
0
;
}
h3
{
text-align
:
center
;
min-height
:
20
dvh
;
margin
:
1rem
auto
;
}
@media
screen
and
(
min-width
:
1024px
)
{
.container
{
...
...
src/components/top-level/task/index.js
View file @
98006a02
...
...
@@ -8,6 +8,25 @@ function Task({ id = 1, title, isCompleted, onChange, onDelete }) {
const
[
debouncetitle
,
setDebounceTitle
]
=
useState
(
title
);
const
[
ischeck
,
setIsCheck
]
=
useState
(
isCompleted
);
const
textarea_ref
=
useRef
(
null
);
//debounce
useEffect
(()
=>
{
//checking the content height and set on page load
// Optional: To ensure the textarea resizes initially if there's content
const
scrollHeight
=
textarea_ref
.
current
.
scrollHeight
-
4
;
textarea_ref
.
current
.
style
.
height
=
`
${
scrollHeight
}
px`
;
//after 2 second it will execute
const
handler
=
setTimeout
(()
=>
{
if
(
textarea_ref
.
current
.
value
!==
title
)
{
onChange
({
id
,
title
:
debouncetitle
});
// toast.success("Task updated");
}
},
2000
);
return
()
=>
{
clearTimeout
(
handler
);
};
},
[
debouncetitle
]);
const
handleDelete
=
(
e
)
=>
{
e
.
preventDefault
();
...
...
@@ -30,51 +49,59 @@ function Task({ id = 1, title, isCompleted, onChange, onDelete }) {
const
handleContent
=
(
e
)
=>
{
setDebounceTitle
(
e
.
target
.
value
);
const
textareaRef
=
textarea_ref
.
current
;
textareaRef
.
addEventListener
(
"input"
,
function
()
{
this
.
style
.
height
=
"
auto
"
;
// Reset the height to auto to calculate the correct scrollHeight
const
scrollHeight
=
this
.
scrollHeight
;
this
.
style
.
height
=
"
25px
"
;
// Reset the height to auto to calculate the correct scrollHeight
this
.
style
.
overflow
=
"hidden"
;
if
(
this
.
scrollTop
===
0
)
{
this
.
style
.
height
=
`
${
scrollHeight
}
px`
;
// Check if the textarea is empty or null and set its height accordingly
if
(
textareaRef
.
value
===
""
||
textareaRef
.
value
===
null
)
{
this
.
style
.
height
=
"25px"
;
// Minimum height of 25px when empty
}
else
{
// If there is overflow (a new line is created), increase the height
this
.
style
.
height
=
`
${
scrollHeight
+
this
.
scrollTop
}
px`
;
// Calculate the new scrollHeight and set the height
const
newScrollHeight
=
Math
.
max
(
this
.
scrollHeight
-
4
,
25
);
// Minimum height of 25px
this
.
style
.
height
=
newScrollHeight
+
"px"
;
}
});
textareaRef
.
addEventListener
(
"keyup"
,
function
(
event
)
{
if
(
event
.
key
===
"Backspace"
&&
(
textareaRef
.
value
===
""
||
textareaRef
.
value
===
null
)
)
{
this
.
style
.
height
=
"25px"
;
// Minimum height of 25px when empty
}
else
{
console
.
log
(
"dkod"
);
this
.
style
.
height
=
"25px"
;
const
newScrollHeight
=
this
.
scrollHeight
-
4
;
// Minimum height of 25px
this
.
style
.
height
=
newScrollHeight
+
"px"
;
}
});
// Optional: To ensure the textarea resizes initially if there's content
textareaRef
.
dispatchEvent
(
new
Event
(
"input"
));
// textareaRef.addEventListener("input", function () {
// this.style.height = "25px"; // Reset the height to auto to calculate the correct scrollHeight
// this.style.overflow = "hidden";
//const textarea = document.querySelector("textarea");
//calculate the height of content based on scrollheight
// textarea.addEventListener("keyup", (e) => {
// let scheight = e.target.scrollHeight;
// textarea.style.height = `${scheight}px`;
// });
};
// // Check if the textarea is empty or null and set its height accordingly
//debounce
useEffect
(()
=>
{
//
checking the content height and set on page load
const
scrollHeight
=
textarea_ref
.
current
.
scrollHeight
;
textarea_ref
.
current
.
style
.
height
=
`
${
scrollHeight
}
px`
;
//
after 2 second it will execute
const
handler
=
setTimeout
(()
=>
{
if
(
textarea_ref
.
current
.
value
!==
title
)
{
onChange
({
id
,
title
:
debouncetitle
});
// toast.success("Task updated");
}
},
2000
);
// // Calculate the new scrollHeight and set the height
// const newScrollHeight = Math.max(this.scrollHeight - 4, 25); // Minimum height of 25px
//
this.style.height = newScrollHeight + "px";
// })
;
// textareaRef.addEventListener("keyup", function (event) {
//
if (
// event.key === "Backspace" &&
// (textareaRef.value === "" || textareaRef.value === null)
// ) {
// this.style.height = "29px"; // Minimum height of 25px when empty
//
}
// else{
return
()
=>
{
clearTimeout
(
handler
);
};
},
[
debouncetitle
]);
// }
// });
};
return
(
<
div
className
=
"task-section"
>
<
div
>
<
div
className
=
"task"
>
<
Checkbox
onChange
=
{
handleChange
}
checked
=
{
ischeck
}
...
...
@@ -86,8 +113,9 @@ function Task({ id = 1, title, isCompleted, onChange, onDelete }) {
className
=
{
`
${
ischeck
?
"strike-through"
:
""
}
`
}
value
=
{
debouncetitle
}
onChange
=
{
handleContent
}
// disabled={ischeck}
><
/textarea
>
/
>
<
/div
>
<
FaTimesCircle
className
=
"fa-close"
onClick
=
{
handleDelete
}
/
>
<
/div
>
...
...
src/components/top-level/task/task.css
View file @
98006a02
.task-section
{
padding
:
1rem
;
display
:
flex
;
align-items
:
center
;
padding
:
0.3rem
1.4rem
;
justify-content
:
space-between
;
border-top
:
1.5px
solid
#e0e0e0
;
/* box-shadow: rgba(0, 0, 0, 0.06) 0px 2px 4px 0px inset; */
clip-path
:
inset
(
0
-100vmax
);
/* clip-path: inset(0 -100vmax); */
}
.task-section
:first-child
{
border-top
:
none
;
}
.task-section
>
div
{
.task
{
height
:
100%
;
display
:
flex
;
align-items
:
center
;
height
:
auto
;
width
:
9
0%
;
justify-content
:
space-between
;
width
:
10
0%
;
}
.fa-close
{
color
:
#ccc
;
...
...
@@ -36,15 +36,11 @@ input:focus {
resize
:
none
;
border
:
none
;
outline
:
none
;
position
:
relative
;
top
:
10px
;
margin-left
:
0.4rem
;
font-size
:
17px
;
color
:
#504e4e
;
font-family
:
"Open Sans"
,
sans-serif
;
font-weight
:
500
;
}
height
:
25px
;
margin
:
0
10px
;
.task-section
textarea
::-webkit-scrollbar
{
width
:
0
;
color
:
#504e4e
;
font-size
:
large
;
font-family
:
system-ui
,
-apple-system
,
BlinkMacSystemFont
,
"Segoe UI"
,
Roboto
,
Oxygen
,
Ubuntu
,
Cantarell
,
"Open Sans"
,
"Helvetica Neue"
,
sans-serif
;
}
src/components/top-level/tasks/tasks.css
View file @
98006a02
...
...
@@ -12,3 +12,6 @@
.fa-close
{
cursor
:
pointer
;
}
.tasklist
{
min-height
:
25
dvh
;
}
src/lib/api.js
View file @
98006a02
...
...
@@ -17,12 +17,11 @@ export async function addTodo({ title, isCompleted }) {
//PATCH METHOD
export
async
function
updateTodo
({
id
,
title
,
isCompleted
})
{
try
{
await
fetch
(
url
+
`/
${
id
}
`
,
{
const
response
=
await
fetch
(
url
+
`/
${
id
}
`
,
{
method
:
"PATCH"
,
headers
:
{
"Content-type"
:
"application/json"
},
body
:
JSON
.
stringify
({
title
,
isCompleted
}),
});
const
response
=
await
getTodos
();
return
response
;
}
catch
(
err
)
{
toast
.
error
(
err
.
message
);
...
...
@@ -45,8 +44,8 @@ export async function deleteTodo(id) {
await
fetch
(
url
+
`/
${
id
}
`
,
{
method
:
"DELETE"
,
});
const
response
=
await
getTodos
();
return
response
;
//
const response = await getTodos();
//
return response;
}
catch
(
err
)
{
toast
.
error
(
err
.
message
);
}
...
...
src/pages/index.js
View file @
98006a02
import
React
from
"react"
;
import
React
,
{
useState
}
from
"react"
;
import
Layout
from
"../components/base/layout"
;
import
Form
from
"../components/top-level/form"
;
import
Tasks
from
"../components/top-level/tasks"
;
...
...
@@ -6,20 +6,27 @@ import { useAppContext } from "../app-context/index";
import
{
useEffect
}
from
"react"
;
export
default
function
Pages
()
{
const
{
todo
,
addTodo
,
getTodos
,
deleteTodo
,
updateTodo
}
=
useAppContext
();
const
{
todo
,
loading
,
addTodo
,
getTodos
,
deleteTodo
,
updateTodo
}
=
useAppContext
();
console
.
log
(
loading
);
useEffect
(()
=>
{
getTodos
();
},
[]);
return
(
<>
<
Layout
count
=
{
todo
?.
filter
((
e
)
=>
!
e
.
isCompleted
).
length
}
>
{
todo
?.
length
>
0
?
(
<
Tasks
tasks
=
{
todo
}
onChange
=
{
updateTodo
}
onDelete
=
{
deleteTodo
}
/
>
)
:
(
<
h3
>
No
task
<
/h3
>
)}
<
Form
onSubmit
=
{
addTodo
}
/
>
<
/Layout
>
{
loading
?
(
<
Layout
count
=
{
todo
?.
filter
((
e
)
=>
!
e
.
isCompleted
).
length
}
>
{
todo
?.
length
>
0
?
(
<
Tasks
tasks
=
{
todo
}
onChange
=
{
updateTodo
}
onDelete
=
{
deleteTodo
}
/
>
)
:
(
<
h3
>
No
task
<
/h3
>
)}
<
Form
onSubmit
=
{
addTodo
}
/
>
<
/Layout
>
)
:
(
"Loading...."
)}
<
/
>
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment