Commit 98006a02 by Madhankumar

auto height textarea and loading

parent a3281ff0
{ {
"task": [ "task": [
{ {
"title": "This HTML file is a template. ", "title": "Buy a tomato ",
"isCompleted": false, "isCompleted": false,
"id": 2 "id": 1
},
{
"title": "This HTML file is a template. ",
"isCompleted": true,
"id": 4
},
{
"title": "hello",
"isCompleted": false,
"id": 5
},
{
"title": "cscdcv",
"isCompleted": false,
"id": 6
}, },
{ {
"title": "vdvdcv", "title": "Go to office",
"isCompleted": false, "isCompleted": false,
"id": 7 "id": 2
},
{
"title": "vdvdv",
"isCompleted": false,
"id": 8
},
{
"title": "ddvdvd",
"isCompleted": true,
"id": 9
},
{
"title": "dvdvdvd",
"isCompleted": false,
"id": 10
}, },
{ {
"title": "wwww", "title": "Party time",
"isCompleted": false, "isCompleted": false,
"id": 11 "id": 3
} }
] ]
} }
\ No newline at end of file
...@@ -6,7 +6,7 @@ export const useAppContext = () => useContext(TodoContext); ...@@ -6,7 +6,7 @@ export const useAppContext = () => useContext(TodoContext);
export function TodoProvider({ children }) { export function TodoProvider({ children }) {
const [todo, setTodo] = useState([]); const [todo, setTodo] = useState([]);
const [loading, setLoading] = useState(false);
//POST METHOD //POST METHOD
async function addTodo({ title }) { async function addTodo({ title }) {
try { try {
...@@ -21,7 +21,11 @@ export function TodoProvider({ children }) { ...@@ -21,7 +21,11 @@ export function TodoProvider({ children }) {
async function updateTodo({ id, title, isCompleted }) { async function updateTodo({ id, title, isCompleted }) {
try { try {
const response = await api.updateTodo({ id, title, isCompleted }); 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) { } catch (err) {
toast.error(err.message); toast.error(err.message);
} }
...@@ -32,6 +36,8 @@ export function TodoProvider({ children }) { ...@@ -32,6 +36,8 @@ export function TodoProvider({ children }) {
try { try {
const response = await api.getTodos(); const response = await api.getTodos();
setTodo(response); setTodo(response);
setLoading(true);
return response;
} catch (err) { } catch (err) {
toast.error(err.message); toast.error(err.message);
} }
...@@ -40,8 +46,9 @@ export function TodoProvider({ children }) { ...@@ -40,8 +46,9 @@ export function TodoProvider({ children }) {
//DELETE METHOD //DELETE METHOD
async function deleteTodo(id) { async function deleteTodo(id) {
try { try {
const response = await api.deleteTodo(id); await api.deleteTodo(id);
setTodo(response);
setTodo(todo.filter((e) => e.id !== id));
} catch (err) { } catch (err) {
toast.error(err.message); toast.error(err.message);
} }
...@@ -49,6 +56,7 @@ export function TodoProvider({ children }) { ...@@ -49,6 +56,7 @@ export function TodoProvider({ children }) {
const value = { const value = {
todo, todo,
loading,
addTodo, addTodo,
getTodos, getTodos,
deleteTodo, deleteTodo,
......
.container { .container {
box-shadow: rgba(0, 0, 0, 0.09) 0px 3px 12px; box-shadow: rgba(0, 0, 0, 0.09) 0px 3px 12px;
background: white; background: white;
min-height: 40vh;
} }
.container h2 { .container h2 {
box-shadow: rgba(0, 0, 0, 0.08) 0px 3px 5px; box-shadow: rgba(0, 0, 0, 0.08) 0px 3px 5px;
...@@ -10,6 +9,12 @@ ...@@ -10,6 +9,12 @@
padding: 1.3rem 0px; padding: 1.3rem 0px;
margin: 0; margin: 0;
} }
h3 {
text-align: center;
min-height: 20dvh;
margin: 1rem auto;
}
@media screen and (min-width: 1024px) { @media screen and (min-width: 1024px) {
.container { .container {
......
...@@ -8,6 +8,25 @@ function Task({ id = 1, title, isCompleted, onChange, onDelete }) { ...@@ -8,6 +8,25 @@ function Task({ id = 1, title, isCompleted, onChange, onDelete }) {
const [debouncetitle, setDebounceTitle] = useState(title); const [debouncetitle, setDebounceTitle] = useState(title);
const [ischeck, setIsCheck] = useState(isCompleted); const [ischeck, setIsCheck] = useState(isCompleted);
const textarea_ref = useRef(null); 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) => { const handleDelete = (e) => {
e.preventDefault(); e.preventDefault();
...@@ -30,51 +49,59 @@ function Task({ id = 1, title, isCompleted, onChange, onDelete }) { ...@@ -30,51 +49,59 @@ function Task({ id = 1, title, isCompleted, onChange, onDelete }) {
const handleContent = (e) => { const handleContent = (e) => {
setDebounceTitle(e.target.value); setDebounceTitle(e.target.value);
const textareaRef = textarea_ref.current; const textareaRef = textarea_ref.current;
textareaRef.addEventListener("input", function () { textareaRef.addEventListener("input", function () {
this.style.height = "auto"; // Reset the height to auto to calculate the correct scrollHeight this.style.height = "25px"; // Reset the height to auto to calculate the correct scrollHeight
const scrollHeight = this.scrollHeight; this.style.overflow = "hidden";
if (this.scrollTop === 0) { // Check if the textarea is empty or null and set its height accordingly
this.style.height = `${scrollHeight}px`; if (textareaRef.value === "" || textareaRef.value === null) {
this.style.height = "25px"; // Minimum height of 25px when empty
} else {
// 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 { } else {
// If there is overflow (a new line is created), increase the height console.log("dkod");
this.style.height = `${scrollHeight + this.scrollTop}px`; 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.addEventListener("input", function () {
textareaRef.dispatchEvent(new Event("input")); // this.style.height = "25px"; // Reset the height to auto to calculate the correct scrollHeight
// this.style.overflow = "hidden";
//const textarea = document.querySelector("textarea"); // // Check if the textarea is empty or null and set its height accordingly
//calculate the height of content based on scrollheight
// textarea.addEventListener("keyup", (e) => {
// let scheight = e.target.scrollHeight;
// textarea.style.height = `${scheight}px`;
// });
};
//debounce // // Calculate the new scrollHeight and set the height
useEffect(() => { // const newScrollHeight = Math.max(this.scrollHeight - 4, 25); // Minimum height of 25px
//checking the content height and set on page load // this.style.height = newScrollHeight + "px";
const scrollHeight = textarea_ref.current.scrollHeight; // });
textarea_ref.current.style.height = `${scrollHeight}px`; // textareaRef.addEventListener("keyup", function (event) {
//after 2 second it will execute // if (
const handler = setTimeout(() => { // event.key === "Backspace" &&
if (textarea_ref.current.value !== title) { // (textareaRef.value === "" || textareaRef.value === null)
onChange({ id, title: debouncetitle }); // ) {
// toast.success("Task updated"); // this.style.height = "29px"; // Minimum height of 25px when empty
} // }
}, 2000); // else{
return () => { // }
clearTimeout(handler); // });
}; };
}, [debouncetitle]);
return ( return (
<div className="task-section"> <div className="task-section">
<div> <div className="task">
<Checkbox <Checkbox
onChange={handleChange} onChange={handleChange}
checked={ischeck} checked={ischeck}
...@@ -86,8 +113,9 @@ function Task({ id = 1, title, isCompleted, onChange, onDelete }) { ...@@ -86,8 +113,9 @@ function Task({ id = 1, title, isCompleted, onChange, onDelete }) {
className={`${ischeck ? "strike-through" : ""}`} className={`${ischeck ? "strike-through" : ""}`}
value={debouncetitle} value={debouncetitle}
onChange={handleContent} onChange={handleContent}
// disabled={ischeck} // disabled={ischeck}
></textarea> />
</div> </div>
<FaTimesCircle className="fa-close" onClick={handleDelete} /> <FaTimesCircle className="fa-close" onClick={handleDelete} />
</div> </div>
......
.task-section { .task-section {
padding: 1rem;
display: flex; display: flex;
align-items: center; align-items: center;
padding: 0.3rem 1.4rem;
justify-content: space-between;
border-top: 1.5px solid #e0e0e0; border-top: 1.5px solid #e0e0e0;
/* box-shadow: rgba(0, 0, 0, 0.06) 0px 2px 4px 0px inset; */ /* 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 { .task-section:first-child {
border-top: none; border-top: none;
} }
.task-section > div { .task {
height: 100%;
display: flex; display: flex;
align-items: center; align-items: center;
height: auto; justify-content: space-between;
width: 90%; width: 100%;
} }
.fa-close { .fa-close {
color: #ccc; color: #ccc;
...@@ -36,15 +36,11 @@ input:focus { ...@@ -36,15 +36,11 @@ input:focus {
resize: none; resize: none;
border: none; border: none;
outline: none; outline: none;
position: relative; height: 25px;
top: 10px; margin: 0 10px;
margin-left: 0.4rem;
font-size: 17px;
color: #504e4e;
font-family: "Open Sans", sans-serif;
font-weight: 500;
}
.task-section textarea::-webkit-scrollbar { color: #504e4e;
width: 0; 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 @@ ...@@ -12,3 +12,6 @@
.fa-close { .fa-close {
cursor: pointer; cursor: pointer;
} }
.tasklist {
min-height: 25dvh;
}
...@@ -17,12 +17,11 @@ export async function addTodo({ title, isCompleted }) { ...@@ -17,12 +17,11 @@ export async function addTodo({ title, isCompleted }) {
//PATCH METHOD //PATCH METHOD
export async function updateTodo({ id, title, isCompleted }) { export async function updateTodo({ id, title, isCompleted }) {
try { try {
await fetch(url + `/${id}`, { const response = await fetch(url + `/${id}`, {
method: "PATCH", method: "PATCH",
headers: { "Content-type": "application/json" }, headers: { "Content-type": "application/json" },
body: JSON.stringify({ title, isCompleted }), body: JSON.stringify({ title, isCompleted }),
}); });
const response = await getTodos();
return response; return response;
} catch (err) { } catch (err) {
toast.error(err.message); toast.error(err.message);
...@@ -45,8 +44,8 @@ export async function deleteTodo(id) { ...@@ -45,8 +44,8 @@ export async function deleteTodo(id) {
await fetch(url + `/${id}`, { await fetch(url + `/${id}`, {
method: "DELETE", method: "DELETE",
}); });
const response = await getTodos(); // const response = await getTodos();
return response; // return response;
} catch (err) { } catch (err) {
toast.error(err.message); toast.error(err.message);
} }
......
import React from "react"; import React, { useState } from "react";
import Layout from "../components/base/layout"; import Layout from "../components/base/layout";
import Form from "../components/top-level/form"; import Form from "../components/top-level/form";
import Tasks from "../components/top-level/tasks"; import Tasks from "../components/top-level/tasks";
...@@ -6,12 +6,16 @@ import { useAppContext } from "../app-context/index"; ...@@ -6,12 +6,16 @@ import { useAppContext } from "../app-context/index";
import { useEffect } from "react"; import { useEffect } from "react";
export default function Pages() { export default function Pages() {
const { todo, addTodo, getTodos, deleteTodo, updateTodo } = useAppContext(); const { todo, loading, addTodo, getTodos, deleteTodo, updateTodo } =
useAppContext();
console.log(loading);
useEffect(() => { useEffect(() => {
getTodos(); getTodos();
}, []); }, []);
return ( return (
<> <>
{loading ? (
<Layout count={todo?.filter((e) => !e.isCompleted).length}> <Layout count={todo?.filter((e) => !e.isCompleted).length}>
{todo?.length > 0 ? ( {todo?.length > 0 ? (
<Tasks tasks={todo} onChange={updateTodo} onDelete={deleteTodo} /> <Tasks tasks={todo} onChange={updateTodo} onDelete={deleteTodo} />
...@@ -20,6 +24,9 @@ export default function Pages() { ...@@ -20,6 +24,9 @@ export default function Pages() {
)} )}
<Form onSubmit={addTodo} /> <Form onSubmit={addTodo} />
</Layout> </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