ooade/NextSimpleStarter

View on GitHub
components/Todo/index.js

Summary

Maintainability
A
3 hrs
Test Coverage
'use client';

import React, { useState } from 'react'
import Image from 'next/image'
import Paper from '@mui/material/Paper'
import TextField from '@mui/material/TextField'
import Grid from '@mui/material/Grid'
import TodoItem from '../TodoItem'
import styles from './index.module.css'



const Todo = () => {
    const initialState = [
        {
            id: 'vnode',
            text: 'A simple initial todo',
            completed: false,
        },
    ]
    const [todos, setTodos] = useState(initialState)
    const [text, setText] = useState('')

    const addTodo = (text) => {
        const todo = {
            id: Math.random().toString(36).substring(2),
            text,
            completed: false,
        }
        setTodos([...todos, todo])
    }

    const removeTodo = (todo) => {
        const filteredTodos = todos.filter((v) => v !== todo)
        setTodos(filteredTodos)
    }

    const updateTodo = (todo) => {
        const updatedTodos = todos.map((v) => (v.id === todo.id ? todo : v))
        setTodos(updatedTodos)
    }

    const completedTodos = todos.filter((todo) => todo.completed)

    const handleAddTodo = (e) => {
        e.preventDefault()
        const trimmedText = text.trim()

        trimmedText && addTodo(trimmedText)
        setText('')
    }

    const handleTextChange = (e) => {
        setText(e.target.value)
    }

    return (
        <Grid
            container
            className={styles.todo}
            justify="center"
            direction="column"
        >
            <header>
                <Image
                    className={styles.logo}
                    src="/static/img/splashscreen-icon-384x384.png"
                    alt=""
                    width="192"
                    height="192"
                />
                <h1 className={styles.srOnly}> Todo App </h1>
            </header>
            <Paper className={styles.paper} elevation={3}>
                <form onSubmit={handleAddTodo} className={styles.form}>
                    <TextField
                        fullWidth
                        value={text}
                        margin="normal"
                        label="What must be done?"
                        onChange={handleTextChange}
                        inputProps={{ 'aria-label': 'What must be done?' }}
                    />
                    <button className={styles.srOnly}> Submit Todo </button>
                    {!!todos.length && (
                        <Grid container justifyContent={'space-between'}>
                            <Grid item>Total: {todos.length}</Grid>
                            <Grid item>Completed: {completedTodos.length}</Grid>
                        </Grid>
                    )}
                </form>
                <ul className={styles.list}>
                    {todos.map((todo) => (
                        <TodoItem
                            key={todo.id}
                            todo={todo}
                            updateTodo={updateTodo}
                            removeTodo={removeTodo}
                        />
                    ))}
                </ul>
            </Paper>
        </Grid>
    )
}

export default Todo;