Commit 35b98601 by Madhankumar

todo component with storybook

parent 4c9e49e7
/** @type { import('@storybook/react').Preview } */ /** @type { import('@storybook/react').Preview } */
import "../src/index.css";
const preview = { const preview = {
parameters: { parameters: {
actions: { argTypesRegex: "^on[A-Z].*" }, actions: { argTypesRegex: "^on[A-Z].*" },
......
{
"task": [
{
"title": "go to office",
"checked": false,
"id": 4
},
{
"title": "meeting in office",
"checked": true,
"id": 5
}
]
}
\ No newline at end of file
...@@ -6,8 +6,10 @@ ...@@ -6,8 +6,10 @@
"@testing-library/jest-dom": "^5.17.0", "@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0", "@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
"json-server": "^0.17.3",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-icons": "^4.10.1",
"react-scripts": "5.0.1", "react-scripts": "5.0.1",
"web-vitals": "^2.1.4" "web-vitals": "^2.1.4"
}, },
...@@ -17,7 +19,8 @@ ...@@ -17,7 +19,8 @@
"test": "react-scripts test", "test": "react-scripts test",
"eject": "react-scripts eject", "eject": "react-scripts eject",
"storybook": "storybook dev -p 6006", "storybook": "storybook dev -p 6006",
"build-storybook": "storybook build" "build-storybook": "storybook build",
"server": "json-server --watch db.json --port 5000 --host 192.168.1.91"
}, },
"eslintConfig": { "eslintConfig": {
"extends": [ "extends": [
......
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
import logo from './logo.svg'; import { useEffect, useState } from "react";
import './App.css'; import "./App.css";
import Layout from "./Components/Base/Layout";
import Tasks from "./Components/TopLevel/Tasks";
import Form from "./Todo/Form";
function App() { function App() {
const [task, setTask] = useState([]);
const addTask = async (data) => {
const res = await fetch(`http://192.168.1.91:5000/task`, {
method: "POST",
headers: { "Content-type": "application/json" },
body: JSON.stringify(data),
});
const result = await res.json();
setTask([...task, result]);
};
const getTask = async () => {
const taskData = await fetch("http://192.168.1.91:5000/task");
const response = await taskData.json();
setTask(response);
};
const getTaskById = async (id) => {
const tasktracker = await fetch(`http://192.168.1.91:5000/task/${id}`);
const response = await tasktracker.json();
return response;
};
const remainder = async (datas) => {
const toogle = await getTaskById(datas.id);
const result = { ...toogle, checked: !toogle.checked };
const res = await fetch(`http://192.168.1.91:5000/task/${datas.id}`, {
method: "PUT",
headers: { "Content-type": "application/json" },
body: JSON.stringify(result),
});
const data = await res.json();
setTask(
task.map((e) => (e.id === data.id ? { ...e, checked: data.checked } : e))
);
};
const deleteTask = async (data) => {
var result = window.confirm("Want to delete?");
if (result) {
//Logic to delete the item
await fetch(`http://192.168.1.91:5000/task/${data.id}`, {
method: "DELETE",
});
setTask(task.filter((e) => e.id !== data.id));
}
};
useEffect(() => {
getTask();
}, []);
return ( return (
<div className="App"> <div className="App">
<header className="App-header"> <Layout count={task.filter((e) => !e.checked).length}>
<img src={logo} className="App-logo" alt="logo" /> {task.length > 0 && (
<p> <Tasks
Edit <code>src/App.js</code> and save to reload. tasksData={task}
</p> handleClick={remainder}
<a handleCloses={deleteTask}
className="App-link" />
href="https://reactjs.org" )}
target="_blank" <Form bottom={true} addtask={addTask} />
rel="noopener noreferrer" </Layout>
>
Learn React
</a>
</header>
</div> </div>
); );
} }
......
.btn{
font-size:18px;
outline:none;
color:black;
border: 1px solid #ccc;
border-radius: 5px;
}
.btn-sm{
padding: 14px 18px;
}
.btn-md {
padding: 16px 20px;
}
.btn-lg {
padding: 18px 25px;
}
import React from 'react' import React from "react";
import PropTypes from "prop-types";
import "../Button/button.css";
function Button() { function Button({ label, backgroundColor, handleClick, size }) {
const style = {
backgroundColor,
};
return ( return (
<div> <div>
<button className={`btn btn-${size}`} style={style} onClick={handleClick}>
{label}
</button>
</div> </div>
) );
} }
export default Button Button.propTypes = {
label: PropTypes.string,
backgroundColor: PropTypes.string,
handleClick: PropTypes.func,
};
Button.defaultProps = {
label: "Submit",
backgroundColor: "white",
};
export default Button;
input[type="checkbox"]{
height:20px;
width:25px;
cursor: pointer;
}
label{
position: absolute;
top: 2.2em;
user-select: none;
}
.chk-bg{
padding: 1rem;
background: white;
}
\ No newline at end of file
import React from 'react' import React from "react";
import "../Checkbox/checkbox.css";
function Checkbox() { function Checkbox({ handleClick, ...args }) {
const handleChange = () => {
args.checked = !args.checked;
let val = args.checked;
console.log(val);
//args.checked = !args.checked;
const result = val ? "checked" : "unChecked";
// console.log(result);
handleClick(result);
};
return ( return (
<div> <div className="chk-bg">
<h1>checkbox</h1> <input
className="chkBox"
type="checkbox"
name="checkbox"
{...args}
onChange={handleChange}
/>
</div> </div>
) );
} }
export default Checkbox export default Checkbox;
import React from 'react' import React from "react";
import "../Input/input.css";
function Input() { function Input({ changeInput, inputValue }) {
const handleChange = (e) => {
e.preventDefault();
changeInput(e.target.value);
};
return ( return (
<div> <>
<h1>input</h1> <input
</div> type="text"
) required
placeholder="Enter Item"
value={inputValue}
onChange={handleChange}
></input>
</>
);
} }
export default Input export default Input;
input[type="text"]{
width:100%;
padding:1rem 1.5rem;
box-sizing: border-box;
border: 1px solid #ccc;
font-size:18px;
outline: none;
box-shadow: rgba(0, 0, 0, 0.12) 0px 2px 4px 0px inset;
border-radius: 5px;
}
\ No newline at end of file
import React from 'react' import "../Layout/layout.css";
function Layout({ count, ...props }) {
function Layout() {
return ( return (
<div> <div className="container">
<h1>layout</h1> <h2 className="header">You have {count || 0} Todos</h2>
<div class="inner-section" {...props}></div>
</div> </div>
) );
} }
export default Layout export default Layout;
.container {
height: 300px;
min-height: 50vh;
width: min(100dvw - 5rem);
margin-inline: auto;
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
background: white;
position: relative;
}
.header {
box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;
border: 1px solid #ccc;
text-align: center;
padding: 1.3rem 0px;
margin: 0;
font-weight: 800px;
background: white;
}
@media screen and (min-width:1024px) {
.container {
width: 40dvw
}
}
import React from 'react'
function Header() {
return (
<div>
<h1>header</h1>
</div>
)
}
export default Header
import React from 'react' import React from "react";
import { FaTimesCircle } from "react-icons/fa";
function Task() { import CheckBox from "../../Base/Checkbox";
import "./task.css";
function Task({ handleClose, handleClicks, task }) {
return ( return (
<div> <>
<h1>task</h1> <div className="task-section">
<div className="task">
<div className="task-title">
<CheckBox handleClick={handleClicks} checked={task.checked} />
<p className={`${task.checked ? "strike-through" : ""}`}>
{task.title}
</p>
</div>
<div className="task-close">
<FaTimesCircle className="fa-close" onClick={handleClose} />
</div>
</div>
</div> </div>
) </>
);
} }
export default Task export default Task;
.task-section {
background: white;
box-shadow: rgba(0, 0, 0, 0.06) 0px 2px 4px 0px inset;
clip-path: inset(0 -100vmax);
}
.task-section .task,
.task-title {
display: flex;
justify-content: space-between;
gap: 0.5rem;
padding: 0.2rem 0.8rem;
align-items: center;
}
.fa-close{
color:#ccc;
font-size:25px
}
.task-section .task,
.task-title>p{
color:#9e9b9b;
}
.strike-through{
text-decoration: line-through;
}
\ No newline at end of file
import React from 'react'
function Tasklist() {
return (
<div>
<h1>tasklist</h1>
</div>
)
}
export default Tasklist
import React from "react";
import "./tasks.css";
import Task from "../../TopLevel/Task";
function Tasks({ handleClick, tasksData, handleCloses }) {
return (
<>
<div className="tasklist">
{tasksData.length > 0
? tasksData.map((tasks) => (
<Task
task={tasks}
handleClicks={() => handleClick(tasks)}
handleClose={() => handleCloses(tasks)}
/>
// <div className="tasks">
// <div className="task-section">
// <div className="task">
// <CheckBox handleClick={handleClicks} />
// <p>{e.title} </p>
// </div>
// <FaTimes
// className="fa-close"
// style={{ color: "red" }}
// onClick={handleClose}
// />
// </div>
// </div>
))
: "No task"}
</div>
</>
);
}
export default Tasks;
.tasks{
box-shadow: rgba(9, 30, 66, 0.25) 0px 1px 1px, rgba(9, 30, 66, 0.13) 0px 0px 1px 1px;
background: white;
padding: 1rem;
}
.tasks .task-section{
margin:0.20rem;
box-shadow: rgba(50, 50, 105, 0.15) 0px 2px 5px 0px, rgba(0, 0, 0, 0.05) 0px 1px 1px 0px;
}
.fa-close{
cursor: pointer;
}
.tasklist{
overflow:auto;
height: 240px;
}
\ No newline at end of file
.form-container{
display: flex;
gap:1rem;
width: calc(100% - 2.5rem);
padding: 1rem;
}
.form-container form{
flex:1;
overflow: auto;
}
.form-bottom{
position:absolute;
bottom: 0;
}
\ No newline at end of file
import React, { useState } from "react";
import Button from "../../Components/Base/Button";
import Input from "../../Components/Base/Input";
import "../Form/form.css";
function Form({ addtask, bottom }) {
const [input, setInput] = useState("");
const submitdata = (e) => {
e.preventDefault();
setInput("");
addtask({ title: input, checked: false });
};
const handleInput = (e) => {
setInput(e);
};
return (
<>
<form onSubmit={submitdata}>
<div className={`form-container ${bottom ? "form-bottom" : ""}`}>
<Input
required={true}
changeInput={(e) => handleInput(e)}
inputValue={input}
/>
<Button size={"md"} />
</div>
</form>
</>
);
}
export default Form;
{
"task":[
]
}
\ No newline at end of file
@import url('https://fonts.googleapis.com/css2?family=PT+Sans:wght@600&family=Poppins:wght@600&display=swap');
body { body {
margin: 0; margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', font-family: "PT Sans", sans-serif;
sans-serif;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} background-image: -webkit-linear-gradient(
-90deg,
code { transparent 0%,
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', transparent 50%,
monospace; white 50%,
white 100%
),
-webkit-linear-gradient(0deg, rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0.1) 50%, white
50%, white 100%);
background-size: 0.2em 0.2em;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
} }
import React from 'react'; import React from "react";
import ReactDOM from 'react-dom/client'; import ReactDOM from "react-dom/client";
import './index.css'; import "./index.css";
import App from './App'; import App from "./App";
import reportWebVitals from './reportWebVitals'; import reportWebVitals from "./reportWebVitals";
const root = ReactDOM.createRoot(document.getElementById('root')); const root = ReactDOM.createRoot(document.getElementById("root"));
root.render( root.render(
<React.StrictMode> // <React.StrictMode>
<App /> <App />
</React.StrictMode> // </React.StrictMode>
); );
// If you want to start measuring performance in your app, pass a function // If you want to start measuring performance in your app, pass a function
......
import Button from "../Components/Base/Button"; import Button from "../Components/Base/Button";
import {action} from '@storybook/addon-actions';
export default{
title:"Base/Button",
component:Button
}
export const button=() => ( export default {
<Button onClick={action('selected')} /> title: "Base/Button",
); component: Button,
argTypes: { handleClick: { action: "Clicked" } },
};
const Template = (args) => <Button {...args} />;
export const button = Template.bind({});
button.args = {
label: "Submit",
backgroundColor: "white",
size: "sm",
};
import Checkbox from "../Components/Base/Checkbox"; import Checkbox from "../Components/Base/Checkbox";
export default{
title:"Base/Checkbox",
component:Checkbox
}
export default {
title: "Base/Checkbox",
component: Checkbox,
argTypes: { handleClick: { action: "clicked" } },
};
export const checkbox = {}; const Template = (args) => <Checkbox {...args} />;
\ No newline at end of file export const checkbox = Template.bind({});
checkbox.args = {
checked: false,
};
import Form from "../Todo/Form";
export default {
title: "Form",
component: Form,
argTypes: { handleSubmit: { action: "Submit" } },
};
const Template = (args) => <Form {...args} />;
export const form = Template.bind({});
form.args = {};
import Header from "../Components/TopLevel/Header";
export default{
title:"TopLevel/Header",
component:Header
}
export const header = {};
\ No newline at end of file
import Input from "../Components/Base/Input"; import Input from "../Components/Base/Input";
export default{ export default {
title:"Base/Input", title: "Base/Input",
component:Input component: Input,
} };
export const input = {}; const Template = (args) => <Input {...args} />;
\ No newline at end of file export const input = Template.bind({});
input.args = {
changeInput: () => {},
};
import Layout from "../Components/Base/Layout"; import Layout from "../Components/Base/Layout";
export default{ export default {
title:"Base/Layout", title: "Base/Layout",
component:Layout component: Layout,
} };
export const layout = {}; const Template = (args) => <Layout {...args} />;
\ No newline at end of file export const layout = Template.bind({});
layout.args = {};
import Task from "../Components/TopLevel/Task"; import Task from "../Components/TopLevel/Task";
export default{ export default {
title:"TopLevel/Task", title: "TopLevel/Task",
component:Task component: Task,
} argTypes: {
handleClose: { action: "Deleted" },
handleClicks: { action: "checked" },
},
};
export const task = {}; const taskData = {
\ No newline at end of file id: "1",
title: "Test Task",
checked: false,
};
const Template = (args) => <Task task={{ ...taskData }} {...args} />;
export const task = Template.bind({});
task.args = {};
import Tasklist from "../Components/TopLevel/TaskList";
export default{
title:"TopLevel/TaskList",
component:Tasklist
}
export const tasklist = {};
\ No newline at end of file
import Tasks from "../Components/TopLevel/Tasks";
import { taskData } from "../Components/TopLevel/Task";
export default {
title: "TopLevel/Tasks",
component: Tasks,
argTypes: {
handleCloses: { action: "Deleted" },
handleClick: { action: "checked" },
},
};
const defaultTasksData = [
{ ...taskData, id: "1", title: "Task 1", checked: false },
{ ...taskData, id: "2", title: "Task 2", checked: true },
{ ...taskData, id: "3", title: "Task 3", checked: true },
];
const Template = (args) => <Tasks tasksData={defaultTasksData} {...args} />;
export const tasks = Template.bind({});
tasks.args = {};
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