Приложение для отслеживания бюджета в React js для начинающих

Обучение на практике — это проверенная основа успеха в любой области. Если вы знаете контекст «Практика делает человека совершенным», здесь я хотел бы добавить «Совершенный» в начале, тогда цитата будет «Совершенная практика делает человека совершенным». Я новичок в React js и недавно сделал приложение Budget Tracker в React.

Будучи полным новичком, я вспомнил цитату, упомянутую ранее, и вместо того, чтобы следовать учебнику на YouTube, я связал свои руки, чтобы написать свой первый проект в React. Несмотря на то, что проект прост и легок в сборке, но новичку создать такой проект будет слишком сложно. Если вы новичок и хотите создать проект, приложение Budget Tracker — лучший вариант. В этой статье я расскажу вам о своем проекте.

Приложение для отслеживания бюджета в React

Создать приложение

Первым шагом для создания любого реактивного проекта является создание реактивного проекта. Для этого вы можете следовать следующим фрагментам кода. Я назову проект Budget_calculator.

npx создать-реагировать-приложение Budget_calculator

Как только вы создали приложение для реагирования, запустите приложение, чтобы убедиться, что оно работает.

запуск нпм

Создать компоненты

Поскольку наше приложение принимает данные от пользователя и отображает транзакцию, как вы видите на упомянутом изображении. Нам нужно сделать двухкомпонентную папку. Один я назвал form для раздела ввода, а main — вторым для раздела отображения или транзакций. Вы можете назвать их по своему желанию.

Добавьте компонент

На этом этапе я создал разные компоненты по отдельности, так как мне нравилось четко разделять вещи, чтобы в них было легко ориентироваться и понимать. Давайте подумаем об основном компоненте, этот компонент будет включать в себя Доход, Расход и Остаток баланса. Кроме того, в этом разделе будет отображаться транзакция и навигационная ссылка или кнопка для создания формы, верно?

В соответствии с этой концепцией я создал компоненты Бюджет, Баланс, Транзакция и Нижний колонтитул. Бюджет является основным компонентом в разделе main, поскольку он объединяет все компоненты для правильного отображения. Аналогичным образом компонент Баланс будет отображать Общий доход, Расход и общий остаток. Также компонент Транзакции будет отображать все транзакции, добавленные пользователем через раздел формы. Наконец, компонент нижнего колонтитула будет использоваться для перехода к форме следующего раздела, чтобы предоставить пользователю раздел ввода.

Затем для компонента формы компонент AddNew будет действовать как компонент Parent для компонента Enter и Select. Компонент «Выбрать» будет содержать элемент выбора, независимо от того, является ли новая добавленная транзакция доходом или расходом. Кроме того, он будет отображать категорию соответствующего дохода или расхода в соответствии с выбором, сделанным пользователем. Точно так же Enter будет иметь раздел ввода для суммы и описания транзакции. Это будет конец части.

Создать дизайн пользовательского интерфейса

Следующей задачей является разработка шаблона или интерфейса. Прежде всего, я разработал его для основного компонента, в котором представлены доход, расход и транзакция. Вы можете проектировать в соответствии с вашими идеями и творчеством. Точно так же вы можете черпать вдохновение из любого дизайна, доступного в Интернете. Здесь я хотел бы предложить вам сосредоточиться на изучении реакции, а не на дизайне.
Я создал и связал отдельный CSS для каждого компонента. Я упомяну окончательную структуру файлов и папок моего проекта.

//index.css
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}

//App.css


.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);
  }
}
//Balance.css
.income {
    display: inline-block;
    margin-right: 50%;
}

.expense {
    display: inline-block;
}

//Budget.css

.full {
    width: 70%;
    height: 80%;
    background-color: bisque;
    border: 5px solid black;
    margin: auto;
}

.hr {
    color: black;
    
}

.App {
    text-align: center;
}

//Footer.css

.btn {
    background-color: #0c80df;
    border: none;
    color: white;
    padding: 16px 32px;
    margin: 2px 0 10px ;
}
//Transaction.css

.in {
    color: green;
}

.exp {
    color: red;
}

.title, amount {
    display: inline-block;
    margin: 0;
    padding: 1rem;
    
}

.title {
    text-align: left;
    
}

.amount {
    text-align: right;
    float: right;
    padding-right: 10em;
}

//AddNew.css
.box {
    width: 70%;
    height: 80%;
    background-color: bisque;
    border: 5px solid black;
    margin: auto;
}

.text {
    text-align: center;
}
//Enter.css
.save {
    background-color: #0cdf5d;
    border: none;
    color: white;
    padding: 16px 32px;
    margin: 10px 10px 10px;
}

.close {
    background-color: #6a6e6c;
    border: none;
    color: white;
    padding: 16px 32px;
    margin: 10px 10px 10px;
}

//Select.css

.select1 {
    
    display: inline-block;
    margin: 5px;
}

.select2 {
    display: inline-block;
    margin: 5px 0 0 20px;
}

Давайте начнем кодировать часть приложения для отслеживания бюджета в React

Прежде всего, я устанавливаю react-router-dom для навигации. Затем я импортирую BrowserRouter в компонент index.js. Точно так же я импортирую Route и Routes в App js, чтобы управлять маршрутом проекта. Я сделал компонент «Бюджет» родительским, а затем компонент «Добавить новый» мог перемещаться по ссылке /add’.

npm установить реакцию-маршрутизатор-дом

//Index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom';

ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

//App.js

import Budget from './components/main/Budget';
import { Route, Routes } from 'react-router';
import AddNew from './components/form/AddNew';
import './App.css';


function App() {

  return (
    <>

    <Routes>
      <Route path = '/' element = {<Budget />} />
      <Route path = '/add' element = {<AddNew  />} />
    </Routes>
    </>
  );
}

export default App;

ДобавитьНовый компонент

Компонент AddNew имеет функциональность для выбора и ввода суммы пользовательских транзакций. В этом компоненте у меня был хук import useState, и я использовал его для создания различных переменных состояния. Состояние параметра используется для проверки того, является ли транзакция, совершенная пользователем, доходом или расходом. Аналогично, состояния доходов и расходов создаются для хранения типа выполненной транзакции. Точно так же создается сумма для хранения суммы совершенных транзакций. В то время как Detail содержит описание транзакций.

Здесь я импортировал хук useFecth. Это пользовательский хук, и я объясню его позже в статье. handleBudget будет запускаться при отправке формы из компонента ввода. Это загрузит и сохранит весь ввод, сделанный пользователем.

//AddNew.js
import Enter from "./Enter";
import Select from "./Select";
import './AddNew.css';
import { useState, useEffect } from 'react';
import useFetch from "../../useFetch";


const AddNew = () => {

  const [budget, setBudget] = useFetch('budget', []);

  const [option, setOption] = useState('income');
  const [income, setIncome] = useState('Salary')
  const [expense, setExpense] = useState('Education')
  const [amount, setAmount] = useState('')
  const [detail, setDetail] = useState('')


const handleBudget = (e) => {
  
    e.preventDefault();


    let budgets = {
      option,
      amount,
      detail,
      income: option == 'income' ? income : '',
      expense:option != 'income' ? expense : ''
    }
    setBudget([...budget, budgets]);
    setOption('income');
    setIncome('Salary');
    setExpense('Education');
    setAmount('');
    setDetail('');

  } 


  // useEffect(() => {
  //   // dataToNew(budget);
  //  if(budget?.length){
  //     localStorage.setItem('budget', JSON.stringify(budget));
  //  }
  
  // }, [budget])
  

  return (
    <>
    <div className="text">
      <h2>Add New Budget List</h2>
    
    <div className="box">
      <Select option = {option} setOption = {setOption} income = {income} expense={expense} setIncome= {setIncome} setExpense = {setExpense} />
      <Enter amount = {amount} setAmount = {setAmount} detail = {detail} setDetail = {setDetail} handleBudget = {handleBudget} />
      
    </div>
    
    </div>
    </>
  )
}

export default AddNew;

//Enter.js
import './Enter.css';
import { NavLink } from 'react-router-dom';

  const Enter = ({ amount, setAmount, detail, setDetail, handleBudget}) => {


  return (
    <>
    <form onSubmit={handleBudget}>

      <h2>Enter Amount</h2>

      <input type="number"
      placeholder='Enter Amount'
      className='amount_field'
      onChange = {(e) => setAmount(parseInt(e.target.value))}
      value={amount}
      required
      />

      <h2>Enter Details</h2>

      <input type="text"
      placeholder='Enter Details'
      className='details_field'
      onChange = {(e) => setDetail(e.target.value)}
      value={detail}
      required
      />

      <br />

     <NavLink to = '/'><button className='close'>Cancel</button></NavLink>

      <button type = "submit" value="Save" className='save'>Save</button>
      
    </form>
    
    
    </>
  )
}

export default Enter;

//Select.js
import './Select.css';
import { useEffect } from 'react';

const Select = ({ option, setOption, income, setIncome, expense, setExpense}) => {


  const datas = [
    {
      id : 1,
      income : "Salary",
      expense : "Education"
    },
    {
      id : 2,
      income : "Stock",
      expense : "Transportation"
    },
    {
      id : 3,
      income : "Mutual Fund",
      expense : "Furniture"
    }
  ]


  useEffect(() => {
    setIncome(datas[0]?.income)
    setExpense(datas[0]?.expense)
  
    
  }, [option])
  

  return (
    <div className='data'>
      <select className='select1' value= {option} onChange = {(e) => setOption(e.target.value)}>
        <option value='income'>Income</option>
        <option value='expense'>Expense</option>
        
        
      </select>
      
      {(option == 'income') ? 
      
      <select className='select2' value={income} key={datas.id}onChange = {(e) => setIncome(e.target.value)}>
       
      {datas.map((data) => {
        return (
          <option key={data.id} value = {data.income} >{data.income}</option>
        )
      })}
      </select>

      :
    
      <select className='select2' value={expense} key={datas.id} onChange = {(e) => setExpense(e.target.value)}>

      {datas.map((data) => {
      return (
        <option key = {data.id} value={data.expense}>{data.expense}</option>
      )
      })}
    </select>
}
    </div>
  )
}

export default Select;

Компонент бюджета

Этот компонент является родительским компонентом основного раздела. Он состоит из тега заголовка для отображения калькулятора бюджета. Кроме того, у него есть дочерние компоненты, такие как Баланс, Транзакция и Нижний колонтитул.

import './Budget.css';
import Balance from './Balance';
import Transaction from './Transaction';
import Footer from './Footer';

const Budget = () => {

  return (
      <div className="App">
          <h2>Budget Calculator</h2>
    <div className="full">
        <Balance />
        <hr className='hr' />
        <Transaction />
        <Footer />
    </div>
    </div>
  )
}

export default Budget;

Компонент баланса

Компонент Balance извлекает данные из useFetch в переменной состояния значения. Значение используется для отображения внутри хука useEffect для получения соответствующего ввода пользователя. Такой ввод отображается в разделе доходов или расходов. Сумма будет рассчитана, а оставшийся баланс будет отображаться в разделе «Общий баланс».

//Balance.js
import './Balance.css';
import useFetch from '../../useFetch';
import { useState, useEffect } from 'react';


const Balance = () => {

    const [ value ] = useFetch('budget', []);
    const [incomeAmount, setIncomeAmount] = useState(0);
    const [expenseAmount, setExpenseAmount] = useState(0);


    let total_income = 0;
    let total_expense = 0;

    useEffect(() => {
        {value.map((d) => {
        if (d.option === 'income' && d.expense === '') {
            total_income += d.amount
        setIncomeAmount(total_income)
    }else{
        total_expense += d.amount
        setExpenseAmount(total_expense)
    }
    })}
    }, [value])


  return (
    <div className="top">
            <div className="total">
                <h3>Total Balance : Rs  {incomeAmount - expenseAmount } </h3>
            </div>
            <div className="rem">
                <div className="income">
                    <h3>Income</h3>
                    <p>Rs {incomeAmount} </p>
                </div>
                <div className="expense">
                    <h3>Expense</h3>
                    <p>Rs {expenseAmount}</p>
                </div>
            </div>
        </div>
  )
}

export default Balance;

//Transaction.js
import './Transaction.css';
import useFetch from '../../useFetch';

const Transaction = () => {

  const [ Value ] = useFetch('budget', []);


  return (
    <div className="middle">
      <h2 style={{color : 'blue' }}>Transaction</h2>
      
      {Value.map((v) => {
        return (
          <>
          {v.option === 'income' ? 
          <div className="in">
          <h3 className='title'>{v.income}</h3>
          <p className='amount'>Rs {v.amount}</p>
      </div> 
      : 
      <div className="exp">
          <h3 className='title'>{v.expense}</h3>
          <p className='amount'>Rs {v.amount}</p>
      </div> 
        }
          </>
        )
      })}
      <hr />
    </div>
  )
}

export default Transaction;

//Footer.js

import './Footer.css';
import { NavLink } from 'react-router-dom';

const Footer = () => {
  return (
    <div className="footer">
      
        <NavLink to = '/add'>
          <button className='btn'>Add New</button>
        </NavLink>
    </div>
  )
}

export default Footer;

Пользовательский хук UseFetch

Этот хук был создан в папке src. Основная цель хука — сохранить ввод пользователя в локальном хранилище и получить каждое значение транзакции для дальнейшего использования. Localstorage.setItem сохраняет входные данные в локальном хранилище, а getStorageValue используется для извлечения данных из локального хранилища.

import { useState, useEffect } from "react";

function getStorageValue(key, []) {
  
  const saved = localStorage.getItem(key);
  const initial = JSON.parse(saved);
  return initial || [];
}

export const useFetch = (key, []) => {
  const [value, setValue] = useState(() => {
    return getStorageValue(key, []);
  });

  useEffect(() => {
    // storing input name
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  return [value, setValue];
};

export default useFetch;

Заключение

Вот мы и подошли к концу руководства по созданию приложения для отслеживания бюджета в React. Мы охватываем почти все, что необходимо для создания приложения. Надеюсь, вы создали свой калькулятор бюджета. Если у вас есть какие-либо проблемы, вы можете посетить мой репозиторий GitHub или задать свой вопрос прямо в разделе комментариев, я буду рад вам помочь.

Спасибо за ваше время, и я надеюсь, вам понравилось много. Если вам понравилась эта статья, пожалуйста, поделитесь ею со своим кругом разработчиков React. Я ценю ваши отзывы.

Источник: Техбаг