Commit 98006a02 by Madhankumar

auto height textarea and loading

parent a3281ff0
{
"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
......@@ -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,
......
.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: 20dvh;
margin: 1rem auto;
}
@media screen and (min-width: 1024px) {
.container {
......
......@@ -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>
......
.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: 90%;
justify-content: space-between;
width: 100%;
}
.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;
}
......@@ -12,3 +12,6 @@
.fa-close {
cursor: pointer;
}
.tasklist {
min-height: 25dvh;
}
......@@ -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);
}
......
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...."
)}
</>
);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment