Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лаб4

.docx
Скачиваний:
0
Добавлен:
02.08.2026
Размер:
98 Кб
Скачать

Министерство цифрового развития, связи и массовых коммуникаций РФ

ордена Трудового Красного Знамени федеральное государственное

бюджетное образовательное учреждение высшего образования

«МОСКОВСКИЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ СВЯЗИ И

ИНФОРМАТИКИ»

Кафедра «МКиИТ»

Лабораторная № 4

по дисциплине «Разработка кроссплатформенного программного обеспечения»

Выполнил:

студент группы БФИ2203

Мячина Л. А.

Проверил:

Потапченко Т. Д.

Москва, 2024 г.

Цель работы:

Изучить принципы маршрутизации (routing) в React-приложениях и внедрить функциональность Drag-and-Drop (DND) через реализацию расширенной версии To-Do листа с несколькими колонками задач. Также студенты познакомятся с библиотеками для работы с DND в React, такими как reactbeautiful-dnd, и научатся управлять состояниями между компонентами с помощью маршрутизатора и системы перетаскивания задач.

Требования к работе:

1. Добавьте два дополнительных столбца. Студентам необходимо добавить два новых столбца (например, "Done" и "Blocked") в существующий DND функционал. Эти колонки должны поддерживать возможность перетаскивания задач.

2. Реализуйте возможность удаления задач. Добавьте в каждый элемент задачу удаления с помощью кнопки. При нажатии задача должна удаляться из списка.

3. Стилизация приложения. Улучшите внешний вид страниц, добавив стили с использованием CSS или библиотеки TailwindCSS.

4. Навигация между страницами. Добавьте в каждую страницу кнопку или ссылку для перехода на другую страницу. Например, на странице с DnD можно добавить ссылку "Перейти к обычному To-Do листу", и наоборот.

Выполнение работы:

Листинг кода

import React from 'react';

import { HashRouter as Router, Route, Routes} from 'react-router-dom'

import TodoPage from './pages/TodoPage';

import DndPage from './pages/DndPage';

function App() {

  return (

    <Router>

      <Routes>

        <Route path="/" element={<TodoPage/>} />

        <Route path="/dnd" element={<DndPage/>} />

      </Routes>

    </Router>

  );

}

export default App;

import React, { useState } from 'react';

import TodoList from '../components/TodoList';

import { useNavigate } from 'react-router-dom';

function TodoPage() {

  const nav = useNavigate();

  const [todos, setTodos] = useState([

    { id: 1, title: 'Buy groceries', completed: false },

    { id: 2, title: 'Read a book', completed: false },

  ]);

  const [newTodo, setNewTodo] = useState('');

  const [isFiltered, setFiltered] = useState(false);

  const [beforefilteredTodos, setBeforeFilteredTodos] = useState([]);

 

  const toggleTodo = (id) => {

    setTodos(

      todos.map((todo) =>

        todo.id === id ? { ...todo, completed: !todo.completed } : todo

      )

    );

  };

  const changeFilter = (mode) => {

   

    switch (mode)

    {

      case "completed":

        if (isFiltered === false) setBeforeFilteredTodos(todos);

        if (beforefilteredTodos.length !== 0) setTodos(beforefilteredTodos);

        setTodos((td) => td.filter((todo) => todo.completed === true));

        setFiltered(true);

        break;

      case "uncompleted":

        if (isFiltered === false) setBeforeFilteredTodos(todos);

        if (beforefilteredTodos.length !== 0) setTodos(beforefilteredTodos);

        setTodos((td) => td.filter((todo) => todo.completed === false));

        setFiltered(true);

        break;

      default:

        if (beforefilteredTodos.length === 0) break;

        setTodos(beforefilteredTodos);

        setFiltered(false);

        break;

    }

  }

  const removeTodo = (id) => {

    setTodos((prevTodos) => prevTodos.filter((todo) => todo.id !== id));

  };

 

  const addTodo = (e) => {

    e.preventDefault();

    if (!newTodo) return;

    const newTodoItem = {

      id: Date.now(),

      title: newTodo,

      completed: false,

    };

    setTodos([...todos, newTodoItem]);

    setNewTodo('');

  };

 

  return (

    <div>

      <button

          style={{

              position: 'absolute',

              top: '5px',

              right: '5px',

          }}

          onClick={() => nav('/dnd')}

      >

          Dnd

      </button>

      <div id="main">

        <h1>My To-Do List</h1>

        <form onSubmit={addTodo}>

          <input

            type="text"

            value={newTodo}

            onChange={(e) => setNewTodo(e.target.value)}

            placeholder="Add new task..."

          />

          <button type="submit">Add</button>

        </form>

        <button type="button" onClick={() => changeFilter('none')}>Все</button>

        <button type="button" onClick={() => changeFilter('completed')}>Выполненные</button>

        <button type="button" onClick={() => changeFilter('uncompleted')}>Не выполненные</button>

        <TodoList todos={todos} toggleTodo={toggleTodo} removeHandle={removeTodo} />

    </div>

  </div>

 );

}

export default TodoPage;

import React, { useState } from 'react';

import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd';

import { useNavigate } from 'react-router-dom';

function DndPage() {

    const nav = useNavigate();

    const [columns, setColumns] = useState({

        todo: {

            name: 'To Do',

            items: [

                { id: '1', content: 'First task' },

                { id: '2', content: 'Second task' },

                { id: '3', content: 'Third task' },

                { id: '4', content: 'Fourth task' },

                { id: '5', content: 'Fifth task' },

            ],

        },

        inProgress: {

            name: 'In Progress',

            items: [],

        },

        done: {

            name: 'Done',

            items: [],

        },

        blocked: {

            name: 'Blocked',

            items: [],

        }

    });

    const [newTask, setNewTask] = useState('');    

    const addTask = (e) => {

        e.preventDefault();

        if (!newTask) return;

        const updatedColumn = columns['todo'];

        const newTaskItem = {

            id: Date.now().toString(), content: newTask,

        };

        setColumns({

            ...columns,

            'todo': {

                ...updatedColumn,

                items: [...updatedColumn.items, newTaskItem],

            },

        });

        setNewTask('');

      };

    const onDragEnd = (result, columns, setColumns) => {

        const { source, destination } = result;

        if (!destination) return;

        const sourceColumn = columns[source.droppableId];

        const destColumn = columns[destination.droppableId];

        const sourceItems = [...sourceColumn.items];

        const destItems = [...destColumn.items];

        const [removed] = sourceItems.splice(source.index, 1);

        if (source.droppableId === destination.droppableId) {

            sourceItems.splice(destination.index, 0, removed);

            setColumns({

                ...columns,

                [source.droppableId]: {

                    ...sourceColumn,

                    items: sourceItems,

                },

            });

        }

        else {

            destItems.splice(destination.index, 0, removed);

            setColumns({

                ...columns,

                [source.droppableId]: {

                    ...sourceColumn,

                    items: sourceItems,

                },

                [destination.droppableId]: {

                    ...destColumn,

                    items: destItems,

                },

            });

        }

    };

    const removeItem = (columnId, itemId) => {

        const updatedColumn = columns[columnId];

        const updatedItems = updatedColumn.items.filter(item => item.id !== itemId);

   

        setColumns({

            ...columns,

            [columnId]: {

                ...updatedColumn,

                items: updatedItems,

            },

        });

    }

    return (

        <div style={{

            display: 'flex',

            flexDirection: 'column',

            justifyContent: 'center',

            alignItems: 'center',

            height: '100vh',

            width: '100vw',

            padding: '20px',

            boxSizing: 'border-box',

        }}>

            <h1>Drag And Drop Page</h1>

            <form onSubmit={addTask}>

                <input

                    type="text"

                    value={newTask}

                    onChange={(e) => setNewTask(e.target.value)}

                    placeholder="Add new task..."

                />

                <button type="submit">Add new task</button>

            </form>

            <button

                style={{

                    position: 'absolute',

                    top: '5px',

                    right: '5px',

                }}

                onClick={() => nav('/')}

            >

                Back to normal

            </button>

            <div style={{

                display: 'flex',

                justifyContent: 'center',

                alignItems: 'center',

                width: '100vw',

                padding: '0 20px',

                boxSizing: 'border-box',

                border: '#f9f9f9',

                borderStyle: 'groove',

                borderRadius: '8px',

            }}>

               

                <DragDropContext onDragEnd={(result) => onDragEnd(result, columns, setColumns)}>

                {Object.entries(columns).map(([columnId, column], index) => {

                    return (

                        <div style={{

                            display: 'flex',

                            flexDirection: 'column',

                            alignItems: 'center',

                            paddingBottom: '5px',

                        }} key={columnId}>

                            <h2>{column.name}</h2>

                            <Droppable droppableId={columnId} key={columnId}>

                            {(provided, snapshot) => {

                                return (

                                    <div {...provided.droppableProps} ref={provided.innerRef}

                                        style={{

                                            background: snapshot.isDraggingOver ? 'rgba(10, 10, 30, 0.6)' : 'rgba(10, 10, 30, 0.4)',

                                            padding: 4,

                                            width: 250,

                                            minHeight: 500,

                                        }}>

                                        {column.items.map((item, index) => (

                                            <Draggable key={item.id} draggableId={item.id} index={index}>

                                                {(provided, snapshot) => {

                                                    return (

                                                        <div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}

                                                            style={{

                                                                display: 'flex',

                                                                justifyContent: 'space-between',

                                                                alignItems: 'center',

                                                                userSelect: 'none',

                                                                padding: '4px',

                                                                margin: '0 0 8px 0',

                                                                minHeight: '50px',

                                                                backgroundColor: snapshot.isDragging ? 'rgba(81, 50, 143, 0.5)' : 'rgba(81, 50, 143, 1.0)',

                                                                borderRadius: '5px',

                                                                color: 'white',

                                                                ...provided.draggableProps.style,

                                                            }}>

                                                            {item.content}

                                                            <button

                                                                style={{

                                                                    backgroundColor: 'purple',

                                                                    color: 'white',

                                                                    border: 'none',

                                                                    borderRadius: '3px',

                                                                    cursor: 'pointer',

                                                                }}

                                                                onClick={() => removeItem(columnId, item.id)}

                                                                >

                                                                Remove

                                                            </button>

                                                        </div>

                                                    );

                                                }}

                                            </Draggable>

                                        ))}

                                        {provided.placeholder}

                                    </div>

                                );

                            }}

                            </Droppable>

                        </div>

                    );

                })}

                </DragDropContext>

            </div>

        </div>

    );

}

export default DndPage;

Результат работы

Рисунок 1 – Результат работы

Вывод

С помощью полученных знаний, мы познакомились с основными принципами маршрутизации в React и расширили свое приложение, добавив Drag-and-Drop функциональность. Работая с реальными инструментами разработки, такими как React Router и react-beautiful-dnd, мы приобретаем практические навыки, которые помогут в дальнейшем создавать более сложные и функциональные веб-приложения.

Соседние файлы в предмете Программирование на HTML/CSS/JavaScript (Веб-разработка)