SpendWise - Budget management app (Ruby on Rails + React) - Part 3

WHAT TO KNOW - Sep 10 - - Dev Community

<!DOCTYPE html>





SpendWise: Budget Management App (Ruby on Rails + React) - Part 3

<br> body {<br> font-family: sans-serif;<br> line-height: 1.6;<br> margin: 0;<br> padding: 0;<br> }<br> h1, h2, h3 {<br> margin-top: 1.5em;<br> }<br> img {<br> max-width: 100%;<br> height: auto;<br> display: block;<br> margin: 1em auto;<br> }<br> code {<br> background-color: #eee;<br> padding: 0.2em 0.4em;<br> border-radius: 3px;<br> }<br> pre {<br> background-color: #eee;<br> padding: 1em;<br> border-radius: 3px;<br> overflow-x: auto;<br> }<br>



SpendWise: Budget Management App (Ruby on Rails + React) - Part 3: Building the User Interface with React



Introduction


This article continues the series on building a budget management app called "SpendWise" using Ruby on Rails and React. In Part 1, we set up the Rails backend and established the core data model. Part 2 covered the front-end foundation with React and connected the UI to the Rails API. Now, we'll dive deeper into building the user interface with React, focusing on creating interactive components for managing transactions, budgets, and visualizing financial data.


Understanding React Components


React applications are built using components, which are independent, reusable pieces of UI code. Each component manages its own state and renders its own HTML. This modularity makes development more efficient, organized, and easier to maintain.


Building the Transaction Management UI


Let's focus on building the UI for managing transactions.

  1. Transaction List Component

First, we need a component to display a list of transactions.
import React, { useState, useEffect } from 'react';
import axios from 'axios';

const TransactionList = () =&gt; {
  const [transactions, setTransactions] = useState([]);

  useEffect(() =&gt; {
    const fetchTransactions = async () =&gt; {
      const response = await axios.get('/api/transactions');
      setTransactions(response.data);
    };
    fetchTransactions();
  }, []); // Run the effect only on mount

  return (
  <div>
   <h2>
    Transactions
   </h2>
   <ul>
    {transactions.map((transaction) =&gt; (
    <li key="{transaction.id}">
     {transaction.description} - ${transaction.amount}
    </li>
    ))}
   </ul>
  </div>
  );
};

export default TransactionList;

This component fetches transaction data from the Rails API using axios and renders a list using map.

  1. Transaction Form Component

Next, we need a form to add new transactions.
import React, { useState } from 'react';
import axios from 'axios';

const TransactionForm = () =&gt; {
  const [description, setDescription] = useState('');
  const [amount, setAmount] = useState('');

  const handleSubmit = async (event) =&gt; {
    event.preventDefault();
    await axios.post('/api/transactions', { description, amount });
    setDescription('');
    setAmount('');
  };

  return (
  <form onsubmit="{handleSubmit}">
   <h2>
    Add Transaction
   </h2>
   <div>
    <label htmlfor="description">
     Description:
    </label>
    <input =="" id="description" onchange="{(e)" type="text" value="{description}"/>
    setDescription(e.target.value)}
        /&gt;
   </div>
   <div>
    <label htmlfor="amount">
     Amount:
    </label>
    <input =="" id="amount" onchange="{(e)" type="number" value="{amount}"/>
    setAmount(e.target.value)}
        /&gt;
   </div>
   <button type="submit">
    Add
   </button>
  </form>
  );
};

export default TransactionForm;

This component handles form submission and sends new transaction data to the Rails API.

  1. Visualizing Transaction Data

To gain insights into spending patterns, we can create a simple chart using a charting library like Chart.js.
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import { Line } from 'react-chartjs-2';

const TransactionChart = () =&gt; {
  const [transactions, setTransactions] = useState([]);

  useEffect(() =&gt; {
    const fetchTransactions = async () =&gt; {
      const response = await axios.get('/api/transactions');
      setTransactions(response.data);
    };
    fetchTransactions();
  }, []);

  const data = {
    labels: transactions.map((transaction) =&gt; new Date(transaction.created_at).toLocaleDateString()),
    datasets: [
      {
        label: 'Transaction Amount',
        data: transactions.map((transaction) =&gt; transaction.amount),
        fill: false,
        borderColor: 'blue',
      },
    ],
  };

  return (
  <div>
   <h2>
    Transaction History
   </h2>
   <line data="{data}">
   </line>
  </div>
  );
};

export default TransactionChart;

This component creates a line chart that displays transaction amounts over time.


Building the Budget Management UI


Now let's build the UI for managing budgets.

  1. Budget List Component

Similar to transactions, we need a list to display existing budgets.
import React, { useState, useEffect } from 'react';
import axios from 'axios';

const BudgetList = () =&gt; {
  const [budgets, setBudgets] = useState([]);

  useEffect(() =&gt; {
    const fetchBudgets = async () =&gt; {
      const response = await axios.get('/api/budgets');
      setBudgets(response.data);
    };
    fetchBudgets();
  }, []);

  return (
  <div>
   <h2>
    Budgets
   </h2>
   <ul>
    {budgets.map((budget) =&gt; (
    <li key="{budget.id}">
     {budget.name} - ${budget.amount}
    </li>
    ))}
   </ul>
  </div>
  );
};

export default BudgetList;

This component fetches budget data from the Rails API and renders a list.

  1. Budget Form Component

We need a form to create new budgets.
import React, { useState } from 'react';
import axios from 'axios';

const BudgetForm = () =&gt; {
  const [name, setName] = useState('');
  const [amount, setAmount] = useState('');

  const handleSubmit = async (event) =&gt; {
    event.preventDefault();
    await axios.post('/api/budgets', { name, amount });
    setName('');
    setAmount('');
  };

  return (
  <form onsubmit="{handleSubmit}">
   <h2>
    Add Budget
   </h2>
   <div>
    <label htmlfor="name">
     Name:
    </label>
    <input =="" id="name" onchange="{(e)" type="text" value="{name}"/>
    setName(e.target.value)}
        /&gt;
   </div>
   <div>
    <label htmlfor="amount">
     Amount:
    </label>
    <input =="" id="amount" onchange="{(e)" type="number" value="{amount}"/>
    setAmount(e.target.value)}
        /&gt;
   </div>
   <button type="submit">
    Add
   </button>
  </form>
  );
};

export default BudgetForm;

This component handles form submission and sends new budget data to the Rails API.

  1. Visualizing Budget Data

To visualize budgets and spending against them, we can use another chart.
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import { Bar } from 'react-chartjs-2';

const BudgetChart = () =&gt; {
  const [budgets, setBudgets] = useState([]);
  const [transactions, setTransactions] = useState([]);

  useEffect(() =&gt; {
    const fetchBudgets = async () =&gt; {
      const response = await axios.get('/api/budgets');
      setBudgets(response.data);
    };
    fetchBudgets();
  }, []);

  useEffect(() =&gt; {
    const fetchTransactions = async () =&gt; {
      const response = await axios.get('/api/transactions');
      setTransactions(response.data);
    };
    fetchTransactions();
  }, []);

  const budgetData = budgets.map((budget) =&gt; ({
    label: budget.name,
    amount: budget.amount,
  }));

  const transactionData = budgets.map((budget) =&gt; ({
    label: budget.name,
    amount: transactions.filter((transaction) =&gt; transaction.budget_id === budget.id).reduce((sum, transaction) =&gt; sum + transaction.amount, 0),
  }));

  const data = {
    labels: budgetData.map((item) =&gt; item.label),
    datasets: [
      {
        label: 'Budget',
        data: budgetData.map((item) =&gt; item.amount),
        backgroundColor: 'green',
      },
      {
        label: 'Spending',
        data: transactionData.map((item) =&gt; item.amount),
        backgroundColor: 'red',
      },
    ],
  };

  return (
  <div>
   <h2>
    Budget Summary
   </h2>
   <bar data="{data}">
   </bar>
  </div>
  );
};

export default BudgetChart;

This component creates a bar chart comparing budget amounts to actual spending for each budget category.


Integrating React Components into the App


Finally, we'll combine these components into a cohesive application.
import React from 'react';
import TransactionList from './TransactionList';
import TransactionForm from './TransactionForm';
import BudgetList from './BudgetList';
import BudgetForm from './BudgetForm';
import TransactionChart from './TransactionChart';
import BudgetChart from './BudgetChart';

function App() {
  return (
  <div classname="container">
   <h1>
    SpendWise
   </h1>
   <div classname="section">
    <transactionform>
    </transactionform>
    <transactionlist>
    </transactionlist>
    <transactionchart>
    </transactionchart>
   </div>
   <div classname="section">
    <budgetform>
    </budgetform>
    <budgetlist>
    </budgetlist>
    <budgetchart>
    </budgetchart>
   </div>
  </div>
  );
}

export default App;

This code assembles all the components into a structured layout for the application.


Conclusion


In this article, we explored the process of building an interactive user interface for our "SpendWise" app using React components. We covered creating components for managing transactions and budgets, as well as visualizing data with charts. By breaking down the UI into modular components, we achieved a more organized and efficient development workflow. We also learned how to use state management with React hooks and integrate external libraries like Chart.js to enhance the user experience.


Best Practices


Here are some best practices for building React applications:
  • Component Reusability: Aim for highly reusable components to reduce code duplication.
  • State Management: Use appropriate state management strategies like context or Redux for complex applications.
  • Testing: Write unit tests for components to ensure correctness and maintainability.
  • Code Style: Follow consistent coding standards and linters for code quality.
  • Performance Optimization: Optimize components for performance, especially for large datasets or complex interactions.

By following these principles, you can build robust and user-friendly React applications. Continue exploring the React documentation and community resources to learn more about advanced techniques and patterns.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player