<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Jesus Esquer</title>
    <description>The latest articles on Forem by Jesus Esquer (@jm27).</description>
    <link>https://forem.com/jm27</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F464265%2Feb0db6d5-af51-4262-b129-0c4cad70c452.jpeg</url>
      <title>Forem: Jesus Esquer</title>
      <link>https://forem.com/jm27</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jm27"/>
    <language>en</language>
    <item>
      <title>The Feynman Technique - Explaining Code Quality to My 10-Year-Old Self</title>
      <dc:creator>Jesus Esquer</dc:creator>
      <pubDate>Wed, 26 Mar 2025 12:08:14 +0000</pubDate>
      <link>https://forem.com/jm27/the-feynman-technique-explaining-code-quality-to-my-10-year-old-self-31mm</link>
      <guid>https://forem.com/jm27/the-feynman-technique-explaining-code-quality-to-my-10-year-old-self-31mm</guid>
      <description>&lt;p&gt;Recently, I’ve been learning to program in Python to improve my AI skills, as most AI libraries are Python-friendly. Deep down, I’ve always been curious about Python because of its flexibility and history. As part of this journey, I’ve been researching scientifically backed learning techniques, including the &lt;strong&gt;Feynman Technique&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This technique, developed by Nobel Prize-winning physicist &lt;strong&gt;Richard Feynman&lt;/strong&gt;, focuses on breaking down complex ideas by explaining them in plain language. It has four core steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Identify the concept.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Teach it to a child (or pretend to).&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identify gaps in your understanding.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review &amp;amp; simplify.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I decided to put this technique to the test by explaining &lt;strong&gt;code quality&lt;/strong&gt; to my 10-year-old, always-dreaming self. Code quality can be subjective, but three main pillars are universally important: &lt;strong&gt;complexity, errors, and readability&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Complexity: How Complicated Is Your Code?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp2g4rkfrtwskdg00ndtx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp2g4rkfrtwskdg00ndtx.gif" alt="Code complexity gif" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Complexity measures how intricate the code logic is—things like decision paths and dependencies. Some key metrics include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cyclomatic Complexity:&lt;/strong&gt; Counts the number of independent paths in the code (loops, conditionals).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cognitive Complexity:&lt;/strong&gt; Measures how hard it is for a human to understand the logic.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nested Layers:&lt;/strong&gt; Tracks how deep loops and conditionals go.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Errors: What Can Go Wrong?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Errors represent different types of issues that break your code. Here are the most common ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Syntax Errors:&lt;/strong&gt; When code breaks the language's rules (e.g., missing semicolons, brackets, or incorrect indentation).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logical Errors:&lt;/strong&gt; When the logic is incorrect, leading to unexpected outputs despite the code running.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime Errors:&lt;/strong&gt; Issues encountered during execution, like division by zero or null pointer references.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time Limit Exceeded:&lt;/strong&gt; When code takes too long to execute, often due to inefficient algorithms.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzzz4afahhtu7969i65b1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzzz4afahhtu7969i65b1.gif" alt="Code Errors Explained" width="460" height="338"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Readability: How Easy Is It to Understand?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Readability determines how simple it is for others (or future you) to understand the intent of your code. Some key factors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Naming:&lt;/strong&gt; &lt;code&gt;calculate_order_total()&lt;/code&gt; vs. &lt;code&gt;calc()&lt;/code&gt;—descriptive names matter!
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Formatting:&lt;/strong&gt; Consistent indentation and whitespace improve clarity.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structure:&lt;/strong&gt; Modular functions are better than one giant block of code.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comments:&lt;/strong&gt; Explain the &lt;em&gt;why&lt;/em&gt;, not just the &lt;em&gt;what&lt;/em&gt;.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Complexity vs. Readability: What’s the Difference?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;At first, I struggled to distinguish between &lt;strong&gt;complexity&lt;/strong&gt; and &lt;strong&gt;readability&lt;/strong&gt;—they seemed like the same thing. But this table helped me clarify:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Aspect&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Code Complexity&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Code Readability&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Focus&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Structural/logical intricacy&lt;/td&gt;
&lt;td&gt;Human comprehension&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Concern&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Maintainability/testing difficulty&lt;/td&gt;
&lt;td&gt;Collaborative understanding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Measurement&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Quantitative (cyclomatic score)&lt;/td&gt;
&lt;td&gt;Qualitative (style adherence)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tools&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SonarQube, CodeClimate&lt;/td&gt;
&lt;td&gt;Linters (flake8, pylint)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Optimization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Refactor into smaller functions&lt;/td&gt;
&lt;td&gt;Improve naming/formatting&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In short, &lt;strong&gt;readability is for humans&lt;/strong&gt;, while &lt;strong&gt;complexity is about code structure&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Explaining Code Quality Using My Childhood Bike&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now, how do I explain all this to a hyperactive 10-year-old version of myself? If I start talking about "code complexity," he’ll probably throw something at me. So, let’s use something I loved as a kid—&lt;strong&gt;my bike&lt;/strong&gt;.  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Errors: The Flat Tire Problem&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;One Sunday, I woke up excited for a bike ride, only to find a &lt;strong&gt;flat tire&lt;/strong&gt;. Bummer! I had to fix it (with my dad’s help) before I could ride again.  &lt;/p&gt;

&lt;p&gt;A flat tire is like a &lt;strong&gt;code error&lt;/strong&gt;—when something is broken, the bike (or program) won’t work properly.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExbGZlM2p1cjNtYThjMm4zdW51bnBwb3J4Y2I2NWJveHBqeGp2MGMzMyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2F3ohjURSQk898nuvEbK%2Fgiphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExbGZlM2p1cjNtYThjMm4zdW51bnBwb3J4Y2I2NWJveHBqeGp2MGMzMyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2F3ohjURSQk898nuvEbK%2Fgiphy.gif" alt="flat tire gif" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Complexity: The Rusty Chain Struggle&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I loved my bike, but I didn’t always take care of it. I left it outside in the rain, dropped it on the ground instead of using the kickstand, and only washed it when my dad was washing his car. Over time, the &lt;strong&gt;chain rusted&lt;/strong&gt;, making pedaling much harder.  &lt;/p&gt;

&lt;p&gt;This is just like &lt;strong&gt;code complexity&lt;/strong&gt;—if a program has too many nested loops or convoluted logic, it makes the computer work harder.  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Readability: Sticky Handlebars &amp;amp; Messy Code&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;After playing in the dirt or eating candy, my bike’s handlebars would get &lt;strong&gt;sticky&lt;/strong&gt;, making it hard to steer. If I had cleaned them regularly, I wouldn’t have struggled!  &lt;/p&gt;

&lt;p&gt;The same applies to &lt;strong&gt;code readability&lt;/strong&gt;. If your code is a mess, with unclear variable names (&lt;code&gt;num&lt;/code&gt; instead of &lt;code&gt;clientPhoneNumber&lt;/code&gt;), future programmers—including future &lt;em&gt;you&lt;/em&gt;—will struggle to understand it.  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Final Thoughts: Teaching to Learn&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I enjoyed this exercise and plan to try it with my kids. Teaching—whether to children or adults—helps cement concepts in our own brains. Associating ideas with real-world objects makes learning easier and more fun.  &lt;/p&gt;

&lt;p&gt;If you want to learn more about Feynman’s technique, check out this article:&lt;br&gt;&lt;br&gt;
🔗 &lt;a href="https://www.innovationtraining.org/what-is-the-feynman-technique-and-how-to-use-it-for-learning/" rel="noopener noreferrer"&gt;The Feynman Technique and How to Use It for Learning&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S.&lt;/strong&gt; Take care of your &lt;strong&gt;code&lt;/strong&gt; and your &lt;strong&gt;bikes&lt;/strong&gt;! ❤️  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fub0ow8r7gvv69m4hgcoz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fub0ow8r7gvv69m4hgcoz.gif" alt="Cleaning bicycle gif" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>science</category>
      <category>learning</category>
      <category>code</category>
    </item>
    <item>
      <title>Step-by-Step Guide to Creating a Donations dApp with Stellar SDK</title>
      <dc:creator>Jesus Esquer</dc:creator>
      <pubDate>Thu, 29 Aug 2024 12:13:18 +0000</pubDate>
      <link>https://forem.com/jm27/step-by-step-guide-to-creating-a-donations-dapp-with-stellar-sdk-39j9</link>
      <guid>https://forem.com/jm27/step-by-step-guide-to-creating-a-donations-dapp-with-stellar-sdk-39j9</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Welcome! In this post, we'll guide you through creating a donation dApp powered by the Stellar SDK. This app handles real-time, secure, and transparent transactions using blockchain technology. You can explore the deployed final product &lt;a href="https://jm27.github.io/charity-dapp/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This app aims to create a platform that enables transparent charitable donations. Donors can track how their funds are used and ensure they reach the intended recipients, enhancing trust in charitable organizations.&lt;/p&gt;

&lt;p&gt;This project was also created as an entry for Stellar’s Build Better on Stellar: Smart Contract Challenge. Please check out the submission and give it a like &lt;a href="https://dev.to/jm27/stellar-donations-dapp-ml7"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technologies Used
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Create React App&lt;/strong&gt;: Scaffolding and managing the React application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React&lt;/strong&gt;: The core library for building the user interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stellar SDK&lt;/strong&gt;: Interacting with the Stellar blockchain to process transactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;react-router-dom&lt;/strong&gt;: Handling routing and navigation within the application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Pages&lt;/strong&gt;: Deploying the application.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;This tutorial is friendly for beginners with a basic familiarity with React.js. You'll need Node.js and an IDE, like VS Code. You can find Node.js &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;here&lt;/a&gt; and VS Code &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;p&gt;First, create a React application by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;charity-dapp-ui/
│   .gitignore
│   package-lock.json
│   package.json
│   README.md
├───public
│       icon.jpg
│       index.html
└───node_modules
└───src
    │   App.css
    │   App.js
    │   App.test.js
    │   index.css
    │   index.js
    │   logo.svg
    │   reportWebVitals.js
    │   setupTests.js
    ├───components
    │   │   Home.js
    │   ├───auth
    │   │       Login.js
    │   │       PrivateRoute.js
    │   │       Register.js
    │   └───dashboard
    │       ├───charity
    │       │       CharityDashboard.js
    │       │       CharityProfile.js
    │       ├───common
    │       │       DonationsList.js
    │       └───donor
    │               DonorDashboard.js
    ├───hooks
    │       useSubmitForm.js
    └───utils
        └───stellarSDK
                stellarSDK.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, set up the directory structure as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Root Level Files&lt;/strong&gt;: Configuration and metadata files like &lt;code&gt;.gitignore&lt;/code&gt;, &lt;code&gt;package.json&lt;/code&gt;, and &lt;code&gt;README.md&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;public&lt;/strong&gt;: Static assets like &lt;code&gt;icon.jpg&lt;/code&gt; and &lt;code&gt;index.html&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;node_modules&lt;/strong&gt;: Lists all installed NPM dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;src&lt;/strong&gt;: Source code of the application.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;components&lt;/strong&gt;: Contains React components.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;auth&lt;/strong&gt;: Authentication-related components (&lt;code&gt;Login.js&lt;/code&gt;, &lt;code&gt;PrivateRoute.js&lt;/code&gt;, &lt;code&gt;Register.js&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;common&lt;/strong&gt;: Shared components (&lt;code&gt;Wrapper.js&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;dashboard&lt;/strong&gt;: Dashboard components.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;charity&lt;/strong&gt;: Charity-specific dashboard components (&lt;code&gt;CharityDashboard.js&lt;/code&gt;, &lt;code&gt;CharityProfile.js&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;common&lt;/strong&gt;: Common dashboard components (&lt;code&gt;DonationsList.js&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;donor&lt;/strong&gt;: Donor-specific dashboard components (&lt;code&gt;DonorDashboard.js&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;hooks&lt;/strong&gt;: Custom hooks (&lt;code&gt;useSubmitForm.js&lt;/code&gt;).&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;utils&lt;/strong&gt;: Utility functions and libraries.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;stellarSDK&lt;/strong&gt;: Stellar SDK-related utilities (&lt;code&gt;stellarSDK.js&lt;/code&gt;).&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step-by-Step Development
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installing Stellar SDK
&lt;/h3&gt;

&lt;p&gt;After creating the necessary directories and files, install the Stellar SDK by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save stellar-sdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting Up Routing
&lt;/h3&gt;

&lt;p&gt;Next, set up the router and routes in &lt;code&gt;App.js&lt;/code&gt; by pasting the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import Home from "./components/Home";
import Login from "./components/auth/Login";
import Register from "./components/auth/Register";
import DonorDashboard from "./components/dashboard/donor/DonorDashboard";
import CharityDashboard from "./components/dashboard/charity/CharityDashboard";
import PrivateRoute from "./components/auth/PrivateRoute";
import CharityProfile from "./components/dashboard/charity/CharityProfile";
import "./App.css";

function App() {
  return (
    &amp;lt;Router&amp;gt;
      &amp;lt;Routes&amp;gt;
        &amp;lt;Route path="/" element={&amp;lt;Home /&amp;gt;} /&amp;gt;
        &amp;lt;Route path="/login" element={&amp;lt;Login /&amp;gt;} /&amp;gt;
        &amp;lt;Route path="/register" element={&amp;lt;Register /&amp;gt;} /&amp;gt;
        &amp;lt;Route
          path="/donor-dashboard"
          element={
            &amp;lt;PrivateRoute&amp;gt;
              &amp;lt;DonorDashboard /&amp;gt;
            &amp;lt;/PrivateRoute&amp;gt;
          }
        /&amp;gt;
        &amp;lt;Route
          path="/charity-dashboard"
          element={
            &amp;lt;PrivateRoute&amp;gt;
              &amp;lt;CharityDashboard /&amp;gt;
            &amp;lt;/PrivateRoute&amp;gt;
          }
        /&amp;gt;
        &amp;lt;Route path="/charity-profile" element={&amp;lt;CharityProfile /&amp;gt;} /&amp;gt;
      &amp;lt;/Routes&amp;gt;
    &amp;lt;/Router&amp;gt;
  );
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we import &lt;code&gt;Router&lt;/code&gt;, &lt;code&gt;Routes&lt;/code&gt;, and &lt;code&gt;Route&lt;/code&gt; from &lt;code&gt;react-router-dom&lt;/code&gt;, React’s built-in library for handling routing. Then, we import all the components that will have a route.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Router&lt;/code&gt; wraps around &lt;code&gt;Routes&lt;/code&gt;, where each &lt;code&gt;Route&lt;/code&gt; has a path and an associated component. For private routes, we'll create a &lt;code&gt;PrivateRoute.js&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Navigate } from "react-router-dom";

const PrivateRoute = ({ children }) =&amp;gt; {
  const currentUser = localStorage.getItem("currentUser");

  if (!currentUser) {
    return &amp;lt;Navigate to="/login" /&amp;gt;;
  }

  return children;
};

export default PrivateRoute;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This component ensures that only registered users can access certain routes. It checks for the presence of a "currentUser" item in local storage and redirects the user to the login page if not found.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Components
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Home Component
&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;Home.js&lt;/code&gt;, add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useNavigate } from "react-router-dom";

const Home = () =&amp;gt; {
  const navigate = useNavigate();
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;h1&amp;gt;Welcome to Stellar Decentralized Donations!&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;
          Empowering change, one donation at a time. Whether you’re here to give
          or to receive, our platform makes it simple, transparent, and secure.
          Join our community by logging in or registering today!
        &amp;lt;/p&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;button onClick={() =&amp;gt; navigate("/login")}&amp;gt;Login&amp;lt;/button&amp;gt;
        &amp;lt;button onClick={() =&amp;gt; navigate("/register")}&amp;gt;Register&amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default Home;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Home component includes a greeting, a description, and two buttons that redirect users to the Register and Login pages.&lt;/p&gt;

&lt;h4&gt;
  
  
  Register Component
&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;Register.js&lt;/code&gt;, add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from "react";
import { useNavigate } from "react-router-dom";
import { registerUserInBlockchain } from "../../utils/stellarSDK/stellarSDK";
import useSubmitForm from "../../hooks/useSubmitForm";

function Register() {
  const navigate = useNavigate();
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [inputPublicKey, setInputPublicKey] = useState("");
  const [role, setRole] = useState("donor"); // or charity

  const registerUserInLocal = (publicKey) =&amp;gt; {
    // Validation for name, email, password
    if (!name || !email || !password) {
      alert("Please fill all the fields");
      return;
    }
    const users = JSON.parse(localStorage.getItem("users")) || [];
    const newUser = { name, email, password, role, publicKey };
    users.push(newUser);
    localStorage.setItem("users", JSON.stringify(users));
  };

  const handleRegister = async () =&amp;gt; {
    if (inputPublicKey) {
      registerUserInLocal(inputPublicKey);
    } else {
      let [keyPair] = await registerUserInBlockchain();
      alert(`Registered successfully! 
        Your public key is ${keyPair.publicKey()}
        Private key is ${keyPair.secret()}.
        Please save these keys for future use.
        Private key is not stored anywhere and cannot be recovered!`);
      registerUserInLocal(keyPair.publicKey());
    }
    // Redirect to login page
    navigate("/login");
  };

  const { isLoading, handleSubmit } = useSubmitForm(handleRegister);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h2&amp;gt;Register&amp;lt;/h2&amp;gt;
      &amp;lt;form onSubmit={handleSubmit}&amp;gt;
        &amp;lt;input
          type="text"
          placeholder="Name"
          value={name}
          onChange={(e) =&amp;gt; setName(e.target.value)}
        /&amp;gt;
        &amp;lt;input
          type="email"
          placeholder="Email"
          value={email}
          onChange={(e) =&amp;gt; setEmail(e.target.value)}
        /&amp;gt;
        &amp;lt;input
          type="password"
          placeholder="Password"
          value={password}
          onChange={(e) =&amp;gt; setPassword(e.target.value)}
        /&amp;gt;
        &amp;lt;select value={role} onChange={(e) =&amp;gt; setRole(e.target.value)}&amp;gt;
          &amp;lt;option value="donor"&amp;gt;Donor&amp;lt;/option&amp;gt;
          &amp;lt;option value="charity"&amp;gt;Charity&amp;lt;/option&amp;gt;
        &amp;lt;/select&amp;gt;
        &amp;lt;p&amp;gt;
          If you have a public key, enter it here to link it to your account:
        &amp;lt;/p&amp;gt;
        &amp;lt;input
          type="text"
          placeholder="Public Key"
          value={inputPublicKey}
          onChange={(e) =&amp;gt; setInputPublicKey(e.target.value)}
        /&amp;gt;
        {isLoading ? (
          &amp;lt;button disabled&amp;gt;Loading...&amp;lt;/button&amp;gt;
        ) : (
          &amp;lt;button type="submit"&amp;gt;
            {inputPublicKey ? "Register" : "Register &amp;amp; Create Stellar Account"}
          &amp;lt;/button&amp;gt;
        )}
      &amp;lt;/form&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default Register;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This component handles user registration. It includes form validation, allowing users to either register with an existing Stellar public key or generate a new one. User details are saved in local storage, and if necessary, a new Stellar account is created.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Hook: useSubmitForm
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;useSubmitForm.js&lt;/code&gt;, add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from "react";

const useSubmitForm = (handleSubmitFunction) =&amp;gt; {
  const [isLoading, setIsLoading] = useState(false);

  const handleSubmit = async (e) =&amp;gt; {
    e.preventDefault();
    setIsLoading(true);

    try {
      await handleSubmitFunction();
    } catch (error) {
      console.error("An error occurred:", error);
    } finally {
      setIsLoading(false);
    }
  };

  return { isLoading, handleSubmit };
};

export default useSubmitForm;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This custom hook handles form submissions. It manages loading states and prevents default form behavior to avoid page reloads.&lt;/p&gt;

&lt;h3&gt;
  
  
  Utils: Stellar SDK (registerUserInBlockchain)
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;stellarSDK.js&lt;/code&gt;, add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const StellarSdk = require("stellar-sdk");

const server = new StellarSdk.Horizon.Server(
  "https://horizon-testnet.stellar.org"
);

export const registerUserInBlockchain = async () =&amp;gt; {
  const pair = StellarSdk.Keypair.random();
  const publicKey = pair.publicKey();

  try {
    const response = await fetch(
      `https://friendbot.stellar.org?addr=${encodeURIComponent(publicKey)}`
    );
    const responseJSON = await response.json();
    console.log("SUCCESS! You have a new account :)\n", responseJSON);
    return [pair, publicKey];
  } catch (e) {
    console.error("Error creating test account!", e);
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This utility function registers a user on the Stellar blockchain by generating a key pair and funding the account. Any errors are caught and logged.&lt;/p&gt;

&lt;h3&gt;
  
  
  Login Component
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;Login.js&lt;/code&gt;, add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from "react";
import { useNavigate } from "react-router-dom";

const Login = () =&amp;gt; {
  const navigate = useNavigate();
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  const handleLogin = (e) =&amp;gt; {
    e.preventDefault();
    const users = JSON.parse(localStorage.getItem("users")) || [];
    const user = users.find(
      (user) =&amp;gt; user.email === email &amp;amp;&amp;amp; user.password === password
    );
    if (!user) {
      alert("Invalid credentials");
      return;
    }
    const dashboardPath =
      user.role === "charity" ? "/charity-dashboard" : "/donor-dashboard";
    navigate(dashboardPath);
    localStorage.setItem("currentUser", JSON.stringify(user));
  };

  return (
    &amp;lt;div className="login"&amp;gt;
      &amp;lt;h2&amp;gt;Login&amp;lt;/h2&amp;gt;
      &amp;lt;form onSubmit={handleLogin}&amp;gt;
        &amp;lt;input
          type="email"
          placeholder="Email"
          value={email}
          onChange={(e) =&amp;gt; setEmail(e.target.value)}
        /&amp;gt;
        &amp;lt;input
          type="password"
          placeholder="Password"
          value={password}
          onChange={(e) =&amp;gt; setPassword(e.target.value)}
        /&amp;gt;
        &amp;lt;button type="submit"&amp;gt;Login&amp;lt;/button&amp;gt;
      &amp;lt;/form&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default Login;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Login component checks user credentials against those stored in local storage. If there is a match, the user is redirected to their respective dashboard (Donor or Charity).&lt;/p&gt;

&lt;h3&gt;
  
  
  Charity Components
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Charity Dashboard
&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;CharityDashboard.js&lt;/code&gt;, add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useEffect } from "react";
import { fetchDonationHistory } from "../../../utils/stellarSDK/stellarSDK";
import DonationsList from "../common/DonationsList";
import { Link } from "react-router-dom";

const CharityDashboard = () =&amp;gt; {
  const charityProfile = JSON.parse(localStorage.getItem("currentUser")) || {};
  const [charityPublicKey] = useState(charityProfile.publicKey || "");
  const [charityName] = useState(charityProfile.name || "");
  const [donationHistory, setDonationHistory] = useState([]);

  useEffect(() =&amp;gt; {
    if (!charityPublicKey) return;
    const fetchHistory = async (charityPublicKey) =&amp;gt; {
      const donationHistory = await fetchDonationHistory(charityPublicKey);
      setDonationHistory(donationHistory);
    };
    fetchHistory(charityPublicKey);
  }, [charityPublicKey]);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;h2&amp;gt;Hello, {charityName}! Let's make an impact.&amp;lt;/h2&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;Link to="/charity-profile"&amp;gt;Edit Profile&amp;lt;/Link&amp;gt;
      &amp;lt;h2&amp;gt;Received Donations&amp;lt;/h2&amp;gt;
      &amp;lt;DonationsList donations={donationHistory} /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default CharityDashboard;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This component fetches and displays the charity’s donation history. It also includes a link to edit the charity’s profile.&lt;/p&gt;

&lt;h3&gt;
  
  
  Utils: Stellar SDK (fetchDonationHistory)
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;stellarSDK.js&lt;/code&gt;, add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const fetchDonationHistory = async (sourcePublicKey) =&amp;gt; {
  try {
    const account = await server.loadAccount(sourcePublicKey);

    const transactions = await server
      .transactions()
      .forAccount(account.accountId())
      .call();

    return transactions?.records;
  } catch (e) {
    console.error("An error has occured fetching donation history", e);
  }
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This utility function retrieves all transactions associated with a given Stellar account.&lt;/p&gt;

&lt;h4&gt;
  
  
  DonationList Component
&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;DonationList.js&lt;/code&gt;, add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useEffect } from "react";
import { extractTransactionDetails } from "../../../utils/stellarSDK/stellarSDK";

const DonationsList = ({ donations }) =&amp;gt; {
  const [transactionDetails, setTransactionDetails] = useState([]);

  const formatDate = (dateString) =&amp;gt; {
    const date = new Date(dateString);
    return date.toLocaleString("en-US", { timeZone: "UTC" });
  };

  useEffect(() =&amp;gt; {
    const getTransactionDetails = async (donations) =&amp;gt; {
      try {
        const transactionDetails = await Promise.all(
          donations.map((donation) =&amp;gt; extractTransactionDetails(donation))
        );
        return transactionDetails;
      } catch (error) {
        console.error("Error fetching transaction details:", error);
        return [];
      }
    };

    getTransactionDetails(donations).then((transactionDetails) =&amp;gt;
      setTransactionDetails(transactionDetails)
    );
  }, [donations]);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;ul&amp;gt;
        {transactionDetails?.map(
          (transaction, index) =&amp;gt;
            Number(transaction.amount).toFixed(2) &amp;gt; 0 &amp;amp;&amp;amp; (
              &amp;lt;li key={index}&amp;gt;
                {Number(transaction.amount).toFixed(2)} XLM from{" "}
                {transaction.from} to {transaction.to} on{" "}
                {formatDate(transaction.createdAt)} UTC
              &amp;lt;/li&amp;gt;
            )
        )}
      &amp;lt;/ul&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default DonationsList;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This component displays a list of donations with details such as the donor, recipient, amount, and date.&lt;/p&gt;

&lt;h3&gt;
  
  
  Utils: Stellar SDK (extractTransactionDetails)
&lt;/h3&gt;

&lt;p&gt;Inside stellarSDK.js add at the bottom the following function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const extractTransactionDetails = async (transaction) =&amp;gt; {
  const operations = await fetchOperationsForTransaction(transaction.id);
  const transactionDetails = {
    id: transaction.id,
    createdAt: transaction.created_at,
    amount: 0,
    to: "",
    from: "",
  };

  operations.forEach((operation) =&amp;gt; {
    if (operation.type === "payment") {
      transactionDetails.amount = operation.amount;
      transactionDetails.to = operation.to;
      transactionDetails.from = operation.from;
    }
  });

  return transactionDetails;
};

export const fetchOperationsForTransaction = async (transactionId) =&amp;gt; {
  const url = `https://horizon-testnet.stellar.org/transactions/${transactionId}/operations`;
  const response = await fetch(url);
  const operations = await response.json();

  return operations._embedded.records;
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this util function, we take one transaction as a parameter, then for the transaction we get the operations using fetchOperationsForTransaction, with the transaction id.&lt;/p&gt;

&lt;p&gt;For each operation, we return an object with the amount, to, and from details.&lt;/p&gt;

&lt;h4&gt;
  
  
  Charity Profile
&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;CharityProfile.js&lt;/code&gt;, add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useEffect } from "react";

const CharityProfile = () =&amp;gt; {
  const [charityPublicKey] = useState("");
  const [profile, setProfile] = useState({
    name: "",
    mission: "",
    contact: "",
    goal: 0,
    raised: 0,
  });

  useEffect(() =&amp;gt; {
    const fetchProfile = async (charityPublicKey) =&amp;gt; {
      const mockProfile = {
        name: "Charity Name",
        mission: "Our mission is to help those in need.",
        contact: "contact@charity.org",
        goal: 1000,
        raised: 200, // This should be fetched from the Stellar transactions
      };
      setProfile(mockProfile);
    };
    fetchProfile(charityPublicKey);
  }, [charityPublicKey]);

  const handleInputChange = (e) =&amp;gt; {
    const { name, value } = e.target;
    setProfile((prevProfile) =&amp;gt; ({ ...prevProfile, [name]: value }));
  };

  const saveProfile = () =&amp;gt; {
    // Save profile to blockchain
    console.log("Saving profile to blockchain", profile);
    // Save profile to local storage
    const charityProfile =
      JSON.parse(localStorage.getItem("charityProfile")) || {};
    // Merge the new profile with the existing profile
    // check if public key from charity matches the public key in local storage
    // link the two profiles
    const updatedProfile = { ...charityProfile, ...profile };
    localStorage.setItem("charityProfile", JSON.stringify(updatedProfile));
  };

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Charity Profile&amp;lt;/h1&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;label&amp;gt;Name:&amp;lt;/label&amp;gt;
        &amp;lt;input
          type="text"
          name="name"
          value={profile.name}
          onChange={handleInputChange}
          placeholder="Charity Name"
        /&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;label&amp;gt;Mission:&amp;lt;/label&amp;gt;
        &amp;lt;textarea
          name="mission"
          value={profile.mission}
          onChange={handleInputChange}
          placeholder="Mission"
        /&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;label&amp;gt;Contact:&amp;lt;/label&amp;gt;
        &amp;lt;input
          type="text"
          name="contact"
          value={profile.contact}
          onChange={handleInputChange}
          placeholder="Contact"
        /&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;label&amp;gt;Goal:&amp;lt;/label&amp;gt;
        &amp;lt;input
          type="number"
          name="goal"
          value={profile.goal}
          onChange={handleInputChange}
          placeholder="Goal"
        /&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;label&amp;gt;Raised:&amp;lt;/label&amp;gt;
        &amp;lt;input type="number" name="raised" value={profile.raised} readOnly /&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;button onClick={saveProfile}&amp;gt;Save Profile&amp;lt;/button&amp;gt;
      &amp;lt;h2&amp;gt;Progress&amp;lt;/h2&amp;gt;
      &amp;lt;p&amp;gt;
        {((profile.raised / profile.goal) * 100).toFixed(2)}% of goal reached
      &amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default CharityProfile;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This component allows charities to update their profile information and track the progress of their fundraising efforts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Donor Dashboard
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;DonorDashboard.js&lt;/code&gt;, add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect, useState } from "react";
import {
  fetchDonationHistory,
  sendPayment,
} from "../../../utils/stellarSDK/stellarSDK";
import DonationsList from "../common/DonationsList";
import useSubmitForm from "../../../hooks/useSubmitForm";

const DonorDashboard = () =&amp;gt; {
  const donorProfile = JSON.parse(localStorage.getItem("currentUser")) || {};
  const [sourceSecretKey, setSourceSecretKey] = useState("");
  const [destinationPublicKey, setDestinationPublicKey] = useState("");
  const [amount, setAmount] = useState(0);
  const [donationHistory, setDonationHistory] = useState([]);
  const [donorPublicKey] = useState(donorProfile.publicKey || "");
  const [donorName] = useState(donorProfile.name || "");

  const submitDonation = async (e) =&amp;gt; {
    if (!sourceSecretKey || !destinationPublicKey || !amount) {
      alert("Please fill all the fields");
      return;
    }
    if (isNaN(amount) || parseFloat(amount) &amp;lt;= 0) {
      alert("Please enter a valid amount");
      return;
    }
    try {
      const result = await sendPayment(
        sourceSecretKey,
        destinationPublicKey,
        amount
      );
      if (result.successful) {
        alert("Donation sent successfully!");
      } else {
        alert(
          "Error sending donation. Please double check your details. And try again."
        );
      }
    } catch (error) {
      console.error("Error sending donation:", error);
    }
  };

  const { isLoading, handleSubmit } = useSubmitForm(submitDonation);

  useEffect(() =&amp;gt; {
    if (!donorPublicKey &amp;amp;&amp;amp; isLoading) return;
    const fetchHistory = async (donorPublicKey) =&amp;gt; {
      const donationHisory = await fetchDonationHistory(donorPublicKey);
      setDonationHistory(donationHisory);
    };
    fetchHistory(donorPublicKey);
  }, [donorPublicKey, isLoading]);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h2&amp;gt;Welcome, {donorName}! Ready to make a difference?&amp;lt;/h2&amp;gt;
      &amp;lt;form onSubmit={handleSubmit}&amp;gt;
        &amp;lt;div&amp;gt;
          &amp;lt;label&amp;gt;Source Secret Key:&amp;lt;/label&amp;gt;
          &amp;lt;input
            type="text"
            value={sourceSecretKey}
            onChange={(e) =&amp;gt; setSourceSecretKey(e.target.value)}
            placeholder="Source Secret Key"
          /&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div&amp;gt;
          &amp;lt;label&amp;gt;Destination Public Key:&amp;lt;/label&amp;gt;
          &amp;lt;input
            type="text"
            value={destinationPublicKey}
            onChange={(e) =&amp;gt; setDestinationPublicKey(e.target.value)}
            placeholder="Destination Public Key"
          /&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div&amp;gt;
          &amp;lt;label&amp;gt;Amount&amp;lt;/label&amp;gt;
          &amp;lt;input
            type="number"
            value={amount}
            onChange={(e) =&amp;gt; setAmount(e.target.value)}
            placeholder="Amount"
          /&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;button type="submit" disabled={isLoading}&amp;gt;
          {isLoading ? "Sending..." : "Send Donation"}
        &amp;lt;/button&amp;gt;
      &amp;lt;/form&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;h2&amp;gt;Donation History&amp;lt;/h2&amp;gt;
        &amp;lt;DonationsList donations={donationHistory} /&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default DonorDashboard;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Donor Dashboard allows users to make donations by entering their Stellar secret key, the recipient’s public key, and the amount. It also displays the donor’s transaction history.&lt;/p&gt;

&lt;h3&gt;
  
  
  Utils: Stellar SDK (sendPayment)
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;stellarSDK.js&lt;/code&gt;, add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
export const sendPayment = async (
  sourceSecretKey,
  destinationPublicKey,
  amount
) =&amp;gt; {
  const sourceKeypair = StellarSdk.Keypair.fromSecret(sourceSecretKey);
  const sourcePublicKey = sourceKeypair.publicKey();

  try {
    const account = await server.loadAccount(sourcePublicKey);
    const fee = await server.fetchBaseFee();

    const transaction = new StellarSdk.TransactionBuilder(account, {
      fee,
      networkPassphrase: StellarSdk.Networks.TESTNET,
    })
      .addOperation(
        StellarSdk.Operation.payment({
          destination: destinationPublicKey,
          asset: StellarSdk.Asset.native(),
          amount: amount.toString(),
        })
      )
      .setTimeout(30)
      .build();

    transaction.sign(sourceKeypair);
    const result = await server.submitTransaction(transaction);
    console.log("Success! Results:", result);
    return result;
  } catch (e) {
    console.error("An error has occured sending payment", e);
  }
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This utility function handles the payment process on the Stellar network, signing and submitting transactions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By following this guide, you’ve built a functional charity donation application using the Stellar SDK. This app allows users to make secure, transparent donations and track how their contributions are being used.&lt;/p&gt;

&lt;p&gt;Blockchain technology enhances transparency and builds trust between donors and charitable organizations.&lt;/p&gt;

&lt;p&gt;If you’re interested in expanding this project, consider exploring some of the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multi-currency support.&lt;/li&gt;
&lt;li&gt;Additional authentication methods.&lt;/li&gt;
&lt;li&gt;Integrating a proof-of-use system for donations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to clone the code &lt;a href="https://github.com/jm27/charity-dapp" rel="noopener noreferrer"&gt;here&lt;/a&gt; or test the live app. This guide didn’t cover styling, but the deployed version uses Tailwind CSS for a clean, modern look.&lt;/p&gt;

&lt;p&gt;Thank you for following along! If you encounter any issues, check the console for errors, and don't hesitate to reach out with questions. Happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>stellarchallenge</category>
      <category>web3</category>
    </item>
    <item>
      <title>Stellar Donations dApp</title>
      <dc:creator>Jesus Esquer</dc:creator>
      <pubDate>Sat, 17 Aug 2024 16:34:59 +0000</pubDate>
      <link>https://forem.com/jm27/stellar-donations-dapp-ml7</link>
      <guid>https://forem.com/jm27/stellar-donations-dapp-ml7</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/stellar"&gt;Build Better on Stellar: Smart Contract Challenge &lt;/a&gt;: Build a dApp&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I developed Stellar Donations, a decentralized application (dApp) that connects donors with charities on the Stellar blockchain. &lt;/p&gt;

&lt;p&gt;This platform allows donors to make secure, transparent donations while enabling charities to receive funds directly, track progress, and share their missions. &lt;/p&gt;

&lt;p&gt;The app has distinct functionalities for donors and charities. &lt;/p&gt;

&lt;p&gt;Donors can donate to the charity of their choosing in real-time, while charities can manage their profiles and view donation histories. &lt;/p&gt;

&lt;p&gt;The application features a user-friendly interface with separate dashboards for donors and charities, allowing users to manage donations, track fundraising goals, and maintain profiles with ease. &lt;/p&gt;

&lt;p&gt;Also, its integration with Stellar, ensures that all transactions are secure, transparent, and immutable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Deployed via GitHub pages live at:&lt;br&gt;
&lt;a href="https://jm27.github.io/charity-dapp/" rel="noopener noreferrer"&gt;https://jm27.github.io/charity-dapp/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Code
&lt;/h2&gt;

&lt;p&gt;Repo:&lt;br&gt;
&lt;a href="https://github.com/jm27/charity-dapp" rel="noopener noreferrer"&gt;https://github.com/jm27/charity-dapp&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;The development of this dApp was a deep dive into the Stellar ecosystem. The implementation of real-time transactions leveraging Stellar's blockchain was a key highlight. Donors can contribute directly to their chosen charities, with transactions happening seamlessly through the Stellar network.&lt;/p&gt;

&lt;p&gt;Additionally, I picked up and worked with Stellar APIs, understanding their structure and integrating them into the app. The dynamic interaction with Stellar's features, including key pair generation and transaction management, was both challenging and rewarding.&lt;/p&gt;

&lt;p&gt;Throughout the project, I learned about Stellar transactions, private keys and seeds, and public keys, and got a high-level understanding of elliptic curve cryptography, which underpins the security and performance of the Stellar network. &lt;/p&gt;

&lt;p&gt;I'm particularly proud of the seamless user experience achieved in the app, especially the intuitive process for donors to make transactions and track their contributions.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;Moving forward, I aim to enhance the app's security features, particularly around key management, encryption, and user authentication.&lt;/p&gt;

&lt;p&gt;Enable server-side communication and DB storage.&lt;/p&gt;

&lt;p&gt;I plan to implement a feature that releases a portion of the donation to the charity upfront, with the remaining funds being released once the charity begins posting proof of valid resource utilization.&lt;/p&gt;

&lt;p&gt;This will add an extra layer of accountability and transparency, ensuring that donations are used effectively and for their intended purposes.&lt;/p&gt;

&lt;p&gt;Also to explore ways to expand the platform, possibly integrating more advanced features like multi-currency support or automated reporting tools for charities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Working with Stellar's ecosystem was a positive experience. The availability of resources and the simplicity of the Stellar SDK made the development process smoother. The ecosystem's focus on financial inclusion aligned well with the goals of this project.&lt;/p&gt;

&lt;p&gt;Thanks for the opportunity to participate! &lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>stellarchallenge</category>
      <category>blockchain</category>
      <category>web3</category>
    </item>
    <item>
      <title>How to Build and Publish a Chrome Extension: Step-by-Step Guide to Creating a Custom Session Saver</title>
      <dc:creator>Jesus Esquer</dc:creator>
      <pubDate>Fri, 19 Jul 2024 11:56:54 +0000</pubDate>
      <link>https://forem.com/jm27/how-to-build-and-publish-a-chrome-extension-step-by-step-guide-to-creating-a-custom-session-saver-1j80</link>
      <guid>https://forem.com/jm27/how-to-build-and-publish-a-chrome-extension-step-by-step-guide-to-creating-a-custom-session-saver-1j80</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;Creating a Chrome extension can seem daunting at first. But with the right guidance, it's manageable. This guide will walk you through building and publishing a Chrome extension. Called "Custom Session Saver." This extension allows users to save and restore custom sessions. For example, "Work," "Personal," "Development," etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By the end of this guide, you will have a functional Chrome extension, ready for publishing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F76veduvz77eebgmxyixf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F76veduvz77eebgmxyixf.png" alt="plugin-enabled"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Setup
&lt;/h3&gt;

&lt;p&gt;Start by creating a directory for your project, named "custom_session_storage." Inside this directory, create the following folder structure:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
project\_root/

│

├── background.js          # Background script specified in manifest

├── images/                # Directory for icons

│   ├── icon16.png         # 16x16 icon

│   ├── icon48.png         # 48x48 icon

│   └── icon128.png        # 128x128 icon

├── manifest.json          # Chrome extension manifest file

├── popup.js          # popup script file

├── popup.css          # popup style file

└── popup.html             # Default popup HTML file

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Manifest File
&lt;/h3&gt;

&lt;p&gt;Open &lt;code&gt;manifest.json&lt;/code&gt; and paste the following code:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "manifest_version": 3,
    "name": "Custom Session Saver",
    "version": "1.0",
    "description": "Save and restore custom sessions, for example: 'Work', 'Personal', 'Development', etc.",
    "permissions": [
        "storage",
        "tabs"
    ],
    "background": {
        "service_worker": "background.js"
    },
    "action": {
        "default_popup": "popup.html"
    },
    "icons": {
        "16": "images/icon16.png",
        "48": "images/icon48.png",
        "128": "images/icon128.png"
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this file, we are doing the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Defining the version of the manifest we are using.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Giving it our custom name, version, and description.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adding permissions for "storage" to save local data and "tabs" to manipulate tabs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Setting the background script. This handles all functionality for tabs and session storage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Defining the UI for the popup.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Setting the default icon for the following sizes: 16x16, 48x48, and 128x128.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Background Script
&lt;/h3&gt;

&lt;p&gt;Create &lt;code&gt;background.js&lt;/code&gt; to handle the extension's background processes. Open it up and paste the following code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
console.log("Background script loaded");

chrome.runtime.onInstalled.addListener(() =&amp;gt; {
  console.log("Extension installed");
});

chrome.runtime.onMessage.addListener((message, sender, sendResponse) =&amp;gt; {
  if (message.action === "saveSession") {
    chrome.storage.local.set({ [message.sessionName]: message.session }, () =&amp;gt; {
      console.log(`Session ${message.sessionName} saved.`);
      chrome.runtime.sendMessage({ action: "refreshSessions" });
      if (sendResponse) sendResponse();
    });
  } else if (message.action === "openSession") {
    chrome.storage.local.get([message.sessionName], (result) =&amp;gt; {
      let session = result[message.sessionName];
      if (session) {
        session.forEach((tab) =&amp;gt; {
          chrome.tabs.create({ url: tab.url });
        });
      }
    });
  } else if (message.action === "deleteSession") {
    chrome.storage.local.remove(message.sessionName, () =&amp;gt; {
      console.log(`Session ${message.sessionName} deleted.`);
      chrome.runtime.sendMessage({ action: "refreshSessions" });
      if (sendResponse) sendResponse();
    });
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here we added a console log message and some event listeners:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- onInstalled:&lt;/strong&gt; After installation, this event gets triggered. This logs that the installation was successful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- onMessage:&lt;/strong&gt; This handles events from &lt;code&gt;popup.js&lt;/code&gt;. If the message is to “saveSession,” it saves the session in local storage. If the message is “openSession,” it looks in local storage for that session and opens new tabs based on saved data. Finally, if the message is “deleteSession,” it removes the session name from storage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- sendingMessage:&lt;/strong&gt; To separate concerns, &lt;code&gt;popup.js&lt;/code&gt; handles the refresh session logic. When saving or deleting, we send an event that &lt;code&gt;popup.js&lt;/code&gt; listens for and triggers the refresh.&lt;/p&gt;

&lt;h3&gt;
  
  
  User Interface
&lt;/h3&gt;

&lt;p&gt;Set up the user interface in &lt;code&gt;popup.html&lt;/code&gt;. Open up the file and paste the following code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;

&amp;lt;head&amp;gt;
    &amp;lt;link rel="stylesheet" type="text/css" href="popup.css"&amp;gt;
    &amp;lt;title&amp;gt;Session Saver&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;
    &amp;lt;div class="title-container"&amp;gt;
        &amp;lt;img src="./images/icon48.png" alt="icon" width="25" height="25"&amp;gt;
        &amp;lt;h3 class="title"&amp;gt;Custom Session Saver&amp;lt;/h3&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;/br&amp;gt;
    &amp;lt;div class="input-container"&amp;gt;
        &amp;lt;input class="input" id="sessionName" type="text" placeholder="Enter session name" /&amp;gt;
        &amp;lt;button class="save-session-btn" id="saveSession"&amp;gt;SAVE&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div id="sessions"&amp;gt;
        &amp;lt;ul class="sessions-list" id="sessionsUL"&amp;gt;&amp;lt;/ul&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;script src="popup.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;

&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this file, we added our extension’s style path and title. Inside the body tag, we included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A header with a small icon and title.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A div container with an input, and a button for saving the session.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Another div that will hold our saved sessions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A script tag to import our JavaScript file** &lt;code&gt;popup.js&lt;/code&gt;**.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Script
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;popup.js&lt;/code&gt;, we will handle the UI interactions. Open up the file and paste the following code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;document.addEventListener("DOMContentLoaded", () =&amp;gt; {
  const saveSessionButton = document.getElementById("saveSession");
  const sessionNameInput = document.getElementById("sessionName");
  const sessionsUL = document.getElementById("sessionsUL");

  const loadSessions = () =&amp;gt; {
    while (sessionsUL.firstChild) {
      sessionsUL.removeChild(sessionsUL.firstChild);
    }
    chrome.storage.local.get(null, (sessions) =&amp;gt; {
      for (let sessionName in sessions) {
        let sessionLI = document.createElement("li");
        sessionLI.className = "session";
        let sessionTitle = document.createElement("span");
        sessionTitle.textContent = sessionName;

        let openButton = document.createElement("button");
        openButton.textContent = "OPEN";
        openButton.addEventListener("click", () =&amp;gt; {
          chrome.runtime.sendMessage({ action: "openSession", sessionName });
        });

        let deleteButton = document.createElement("button");
        deleteButton.textContent = "DELETE";
        deleteButton.addEventListener("click", () =&amp;gt; {
          chrome.runtime.sendMessage({ action: "deleteSession", sessionName });
        });

        sessionLI.appendChild(sessionTitle);
        sessionLI.appendChild(openButton);
        sessionLI.appendChild(deleteButton);
        sessionLI.appendChild(document.createElement("br"));
        sessionsUL.appendChild(sessionLI);
      }
    });
  };

  saveSessionButton.addEventListener("click", () =&amp;gt; {
    let sessionName = sessionNameInput.value;
    if (sessionName) {
      chrome.tabs.query({ currentWindow: true }, (tabs) =&amp;gt; {
        let session = tabs.map((tab) =&amp;gt; ({ url: tab.url, title: tab.title }));
        chrome.runtime.sendMessage(
          { action: "saveSession", sessionName, session },
          loadSessions
        );
      });
    }
  });

  chrome.runtime.onMessage.addListener((message) =&amp;gt; {
    if (message.action === "refreshSessions") {
      loadSessions();
    }
  });

  loadSessions();
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Inside this script:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We create a listener on the document, to get triggered when all content has loaded.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We get a couple of elements from the UI: the save session button, the input element, and the sessions list element.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We define a &lt;code&gt;loadSession&lt;/code&gt; method. Inside, we use a while loop to clear the list element, reloading on each change. We retrieve the session property from local storage using Chrome's built-in methods.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We loop through all our sessions using a &lt;code&gt;for-in&lt;/code&gt; loop, creating a &lt;code&gt;li&lt;/code&gt; element and giving it a class name of the session. Create a span to hold our title. A button to open the session when clicked, and a delete button to remove the session when clicked.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We append the title and buttons to our session &lt;code&gt;li&lt;/code&gt; element and this element to our session &lt;code&gt;ul&lt;/code&gt; from &lt;code&gt;popup.html&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We add an event listener to the save session button. On click, it grabs the input value and saves it as the session name. Using Chrome methods, we loop through the current window's open tabs. Then create a map, and send a message to &lt;code&gt;background.js&lt;/code&gt; to save the sessions in local storage. We trigger &lt;code&gt;loadSession&lt;/code&gt; to reload the list and reflect the new item.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We add a listener to handle &lt;code&gt;refreshSessions&lt;/code&gt; messages from &lt;code&gt;background.js&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, we trigger this method on the first load to display existing sessions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Icons
&lt;/h3&gt;

&lt;p&gt;Prepare three icon sizes: 16x16, 48x48, and 128x128 pixels. These are for Chrome's toolbar and the Chrome Web Store.&lt;/p&gt;

&lt;p&gt;Search for free tools like &lt;a href="http://resizeimage.net" rel="noopener noreferrer"&gt;resizeimage.net&lt;/a&gt;, AI icon generator, and FreeConvert. To create and resize your icons.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Famtct9miemohk9vmohvl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Famtct9miemohk9vmohvl.jpg" alt="Icon"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Styles
&lt;/h3&gt;

&lt;p&gt;Style the popup with &lt;code&gt;popup.css&lt;/code&gt; to look user-friendly and smooth. Open up the file and paste the following code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;body {
    width: 300px;
    font-family: Arial, sans-serif;
}

.title-container {
    border-bottom: 1px solid rgba(0, 0, 0, .06);
    display: flex;
    justify-content: flex-start;
    text-align: center;
    align-items: center;
}

.title {
    margin-left: 4px;
}

.input-container {
    margin-top: 4px;
    padding-bottom: 10px;
}

.input {
    border: 1px solid lightgray;
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.1);
    margin-right: 5px;
    border-radius: 4px;
    font-size: larger;
    padding-top: 4px;
    padding-bottom: 4px;
    padding-left: 4px;
}

input:focus-visible,
button:focus-visible {
    outline: 1px solid #007bff;
    outline-offset: 0px;
}

button {
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.1);
    border: none;
    padding: 5px 10px;
    cursor: pointer;
    border-radius: 4px;
}

.save-session-btn {
    background-color: #007bff;
    color: #ffffff;
}

.save-session-btn:hover,
.save-session-btn:active,
.save-session-btn:focus,
.save-session-btn:focus-visible {
    background-color: #0056b3;
}

.sessions-list {
    padding-inline-start: 20px;
}

.session {
    display: flex;
    align-items: center;
    margin-bottom: 15px;
    padding-left: 5px;
}

.session::before {
    content: "\2022";
    display: inline-block;
    width: 20px;
    margin-left: -25px;
    text-align: center;
}

.session span {
    flex-grow: 1;
    font-weight: bold;
    font-size: larger;
}

.session button {
    margin-left: 10px;
    background-color: #ffffff;
    color: #007bff;
    border: 1px solid #007bff;
}

.session button:hover,
.session button:active,
.session button:focus,
.session button:focus-visible {
    background-color: #dbe5f2;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For this style, we aimed for a modern look:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Custom width and font for the whole body.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Text-centered title container with a slight border at the bottom.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A small margin to separate the title from the icon.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Custom styles for the input and buttons, including rounded corners, a bit of shadow, and blue outlines. There are two buttons: one blue-colored and the other with blue outlines.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flex positioning, making list items take the same space as a column with flex-grow. Since "flex" breaks our list items, we added the list item symbol before each.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;To test your extension:&lt;/p&gt;

&lt;p&gt;1. Navigate to Chrome's extension page (chrome://extensions/).&lt;/p&gt;

&lt;p&gt;2. Enable developer mode.&lt;/p&gt;

&lt;p&gt;3. Click "Load unpacked" and select your project directory. Now your extension should be visible in Chrome.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnizq8jx6ggz3s3ssszut.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnizq8jx6ggz3s3ssszut.png" alt="Extension_unpacked_visible"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploying to the Chrome Web Store
&lt;/h3&gt;

&lt;p&gt;Deploying to the Chrome Web Store is straightforward. It does need attention to detail due to Google's review process. Follow these steps:&lt;/p&gt;

&lt;p&gt;1. Zip Your Application: Ensure your project follows the correct folder structure. &lt;code&gt;manifest.json&lt;/code&gt; should be at the root.&lt;/p&gt;

&lt;p&gt;2. Set Up a Developer Account: Navigate to the Chrome Web Store Developer Dashboard. Then pay a one-time fee of $5 to publish extensions.&lt;/p&gt;

&lt;p&gt;3. Upload Your Extension: Click "Add a new item," upload your zip file. Fill out the required details such as title, description, and privacy policy.&lt;/p&gt;

&lt;p&gt;4. Submit for Review: After completing the form, submit your extension for review. This process can take from a few hours to a few days. After the review, you will receive an email.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F61524kbmm9p5g6ba8k7y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F61524kbmm9p5g6ba8k7y.png" alt="submit_for_review_popup"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Enhancements
&lt;/h3&gt;

&lt;p&gt;Consider adding these features to improve your extension:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Renaming sessions or organizing sessions into categories.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implementing test cases for your script file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Interacting with users to gather feedback and improve the extension.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Monetizing your extension by offering a premium version with extra features.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Congratulations, you've accomplished creating a Chrome extension! Added full functionality and styling, and published it to the Chrome Web Store. By following this guide, you have learned extension development and deployment steps. Keep experimenting and enhancing your extension to make it even more useful.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwt3wn7zeqot5q5w1jog6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwt3wn7zeqot5q5w1jog6.png" alt="extension_published"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://chromewebstore.google.com/detail/custom-session-saver/jpcagnjfomlfmlbmlianfjabclkdbdoi?hl=en-US&amp;amp;utm_source=ext_sidebar" rel="noopener noreferrer"&gt;&lt;strong&gt;Public extension link&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jm27/custom_session_ext" rel="noopener noreferrer"&gt;&lt;strong&gt;Code repository&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>extensions</category>
    </item>
    <item>
      <title>Step-by-Step Guide to Creating a Fullstack Mood Tracker CRUD App with React, Node.js, and SQLite.</title>
      <dc:creator>Jesus Esquer</dc:creator>
      <pubDate>Tue, 02 Jul 2024 12:07:33 +0000</pubDate>
      <link>https://forem.com/jm27/step-by-step-guide-to-creating-a-fullstack-mood-tracker-crud-app-with-react-nodejs-and-sqlite-30gb</link>
      <guid>https://forem.com/jm27/step-by-step-guide-to-creating-a-fullstack-mood-tracker-crud-app-with-react-nodejs-and-sqlite-30gb</guid>
      <description>&lt;h5&gt;
  
  
  Introduction
&lt;/h5&gt;

&lt;p&gt;Hi all, welcome, and thanks for stopping by!&lt;/p&gt;

&lt;p&gt;In this step-by-step guide, we will learn how to create a full-stack application with create, read, update, and delete (CRUD) functionality.&lt;/p&gt;

&lt;p&gt;We will use Node.js and SQLite for the backend, and React for the frontend to create our user interface (UI).&lt;/p&gt;

&lt;p&gt;Our project will be a mood tracker app where users can input their mood on a scale of 1-10. The app will display these moods in a list, with options to edit or delete them. Additionally, we will include a linear chart to track and visualize mood trends.&lt;/p&gt;

&lt;p&gt;The final version will look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F184ny9dmxnqr3sbzipwb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F184ny9dmxnqr3sbzipwb.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: This tutorial assumes you have Node.js installed and an IDE installed preferably VScode. If not please go here to install Node.js and here for VScode.&lt;/p&gt;

&lt;p&gt;Ok without further ado, let’s jump to it!&lt;/p&gt;

&lt;h5&gt;
  
  
  Backend Development
&lt;/h5&gt;

&lt;p&gt;We will start with the backend. First, create a backend directory and open it in your favorite IDE. For this article, we will use VS Code.&lt;/p&gt;

&lt;p&gt;After opening the backend directory in your code editor, open the terminal and run the following command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This will register our project as a Node application and create a package.json file inside our directory.&lt;/p&gt;

&lt;p&gt;Next, we need to add our project dependencies. &lt;/p&gt;

&lt;p&gt;We will use Express to create our server, SQLite3 for our database, and Body-Parser to extract the body of requests.&lt;/p&gt;

&lt;p&gt;In the terminal, run:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install express sqlite3 body-parser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After the installation is complete, we will set up our directory structure. &lt;/p&gt;

&lt;p&gt;The folder structure inside the backend directory should look like this (create directories and files as needed):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  /node_modules
  /db
    mood.db
  /routes
    index.js
    mood.js
  /models
    mood.js
  server.js
  package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Open server.js, the main file of the Node.js application, and copy and paste the following code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const sqlite3 = require('sqlite3').verbose();
const bodyParser = require('body-parser');
const app = express();

app.use(bodyParser.json());

let db = new sqlite3.Database('./db.sqlite');

app.get('/', (req, res) =&amp;gt; {
  res.send('Hello World!');
});

app.listen(3000, () =&amp;gt; {
  console.log('Server is running on port 3000');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We imported this code's express, sqlite3, and body-parser modules and initialized a new Express application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We used body-parser as middleware to parse incoming request bodies. We also initialized a new SQLite database (or opened it if it already exists). &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Defined a route handler for GET requests to the root URL (/), and started the server on port 3000.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To run the app with hot reload (so you don't have to restart the server each time you make a change). We can use a dependency called nodemon. &lt;/p&gt;

&lt;p&gt;Install it by running:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev nodemon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To use nodemon, update the scripts section inside package.json. Change the start script to look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"start": "nodemon server.js"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Open your terminal and run:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then, open your default browser and navigate to &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000/&lt;/a&gt;. You should see "Hello World". &lt;/p&gt;

&lt;p&gt;Your terminal should display the following message:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[nodemon] starting `node server.js`
Server started on port 3000
Connected to the mood database.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Congrats, you have created and run an Express server!&lt;/p&gt;

&lt;p&gt;If you don’t see it running, check your terminal for any errors.&lt;/p&gt;

&lt;p&gt;Now let's start working on the model and routes for our application. &lt;/p&gt;

&lt;p&gt;A model defines the structure of an object, and routes perform the CRUD operations. &lt;/p&gt;

&lt;p&gt;Open models/mood.js and add the following code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sqlite3 = require('sqlite3').verbose();

let db = new sqlite3.Database('./db/moods.db', (err) =&amp;gt; {
    if (err) {
        console.error(err.message);
    }
    console.log('Connected to the moods database.');
});

db.run(`CREATE TABLE IF NOT EXISTS moods(
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    mood INTEGER NOT NULL
)`, (err) =&amp;gt; {
    if (err) {
        console.error(err.message);
    }
    console.log("Moods table created");
});

module.exports = db;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this code, we imported SQLite and defined our database. &lt;br&gt;
Created our table with id and mood columns, and exported our database.&lt;/p&gt;

&lt;p&gt;Next, let's create our routes. Copy and paste the following code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require("express");
const router = express.Router();
const db = require("../models/mood");

router.post("/", (req, res) =&amp;gt; {
  const { mood } = req.body;
  const query = `INSERT INTO moods(mood) VALUES(?)`;

  db.run(query, [mood], function (err) {
    if (err) {
      console.error(err.message);
      return res.status(500).json({ message: err.message });
    }
    res.send({ id: this.lastID, mood: mood });
  });
});

router.get("/", (req, res) =&amp;gt; {
  const query = `SELECT * FROM moods`;

  db.all(query, [], (err, rows) =&amp;gt; {
    if (err) {
      console.error(err.message);
      return res.status(500).json({ message: err.message });
    }
    res.send(rows);
  });
});

router.put("/:id", (req, res) =&amp;gt; {
  const { mood } = req.body;
  const { id } = req.params;
  const query = `UPDATE moods SET mood = ? WHERE id = ?`;

  db.run(query, [mood, id], function (err) {
    if (err) {
      console.error(err.message);
      return res.status(500).json({ message: err.message });
    }
    res.send({ id: id, mood: mood });
  });
});

router.delete("/:id", (req, res) =&amp;gt; {
  const { id } = req.params;
  const query = `DELETE FROM moods WHERE id = ?`;

  db.run(query, [id], function (err) {
    if (err) {
      console.error(err.message);
      return res.status(500).json({ message: err.message });
    }
    res.send({ changes: this.changes });
  });
});

module.exports = router;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here, we imported Express to create a server application. &lt;/p&gt;

&lt;p&gt;Using Express, we made a router object to define routes for the mood application. &lt;/p&gt;

&lt;p&gt;We also imported our recently created database model.&lt;/p&gt;

&lt;p&gt;For our CRUD operations, we created a new route for each action:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create: This route responds to all POST requests at the root path (/). We extract the mood from the request and then define a SQL query to insert a new mood. Run the query on our db module, passing the mood value as a parameter. We handle errors and send the response back to the client or a status code of 500 with the error message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Read: This route responds only to GET requests at the root path (/). We define a SQL query to select all moods, run the query, and send back the response with moods if successful. Otherwise, we send a status 500 code with the error message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update: This route responds to PUT requests at the path /:id, mood id should  be in the path like /6. Like POST, we extract the body from the request and get the id from the path. We create a query to update a specific mood based on the id. Then run the query, passing mood and id as parameters, and include error handling logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete: This route responds only to DELETE requests at the path /:id. We get the id from the request, then create a query to delete it from the moods table if it exists, and apply the same error handling logic.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We exported our router object to use the routes in our server.js file.&lt;br&gt;
Let's update our server.js file to include our router. &lt;/p&gt;

&lt;p&gt;Also, remove the database file reference we moved inside our model. Updated server.js:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require("express");
const bodyParser = require("body-parser");
const moodsRouter = require("./routes/mood");
const cors = require("cors");

const app = express();

app.use(cors());
app.use(bodyParser.json());
app.use("/moods", moodsRouter);

app.get("/", (req, res) =&amp;gt; {
  res.send("Hello World!");
});

app.listen(3001, () =&amp;gt; {
  console.log("Server started on port 3001");
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Notice we also added the CORS middleware for local development and switched the port to 3001. &lt;/p&gt;

&lt;p&gt;This will be helpful when integrating and testing our UI. In your terminal, run the following command to install CORS:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev cors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Find out more about CORS &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now start your server app, and let’s test the routes. We can use curl inside the terminal to test.&lt;/p&gt;

&lt;p&gt;Here's how you can do it for each type of request:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;GET request: To fetch all moods, use the following command:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl http://localhost:3001/moods

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftp7n1d26btqlf1ouctzw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftp7n1d26btqlf1ouctzw.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;POST request: To create a new mood, use the -d flag to send data:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$body = @{
    mood = 7
} | ConvertTo-Json

$response = Invoke-WebRequest -Uri http://localhost:3001/moods -Method POST -Body $body -ContentType "application/json"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3s9mrpij2ig0yygyophp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3s9mrpij2ig0yygyophp.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feenju54m2gipd1wp0xwc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feenju54m2gipd1wp0xwc.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;PUT request: To update a mood, you need to know the id of the mood you want to update. Replace :id with the actual id of the mood:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Replace :id with the actual id of the mood you want to update
$id = ":id"

$body = @{
    mood = 8
} | ConvertTo-Json

$response = Invoke-WebRequest -Uri http://localhost:3001/moods/$id -Method PUT -Body $body -ContentType "application/json"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpbjrf7sfz8sv7qgnybor.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpbjrf7sfz8sv7qgnybor.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;DELETE request: To delete a mood, you also need to know the id of the mood. Replace :id with the actual id of the mood:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Replace :id with the actual id of the mood you want to delete
$id = ":id"

$response = Invoke-WebRequest -Uri http://localhost:3001/moods/$id -Method DELETE

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe285jr3y7ujgqkljv860.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe285jr3y7ujgqkljv860.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check your console for any errors. &lt;/p&gt;

&lt;p&gt;You made it all the way here, congratulations! You built an application with CRUD functionality!&lt;/p&gt;

&lt;p&gt;Now we are ready to move to the UI.&lt;/p&gt;

&lt;h5&gt;
  
  
  Frontend Development
&lt;/h5&gt;

&lt;p&gt;For UI development, we first need to create a React app. &lt;/p&gt;

&lt;p&gt;We'll use a tool called Create React App, which provides us with a template application to build on.&lt;/p&gt;

&lt;p&gt;Open a new terminal, change the directory to frontEnd, and then type the following command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-react-app mood-tracker-ui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;npx allows us to run npm packages without installing them. &lt;/p&gt;

&lt;p&gt;It runs create-react-app, the third argument is the directory's name and application.&lt;/p&gt;

&lt;p&gt;Now that we've created our app, change the directory to mood-tracker-ui:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd mood-tracker-ui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let's clean up by removing files and code we won't use. &lt;/p&gt;

&lt;p&gt;Remove the following files: App.test.js, logo.svg, reportWebVitals.js, and setupTests.js.&lt;/p&gt;

&lt;p&gt;We'll clean up index.js to look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  &amp;lt;React.StrictMode&amp;gt;
    &amp;lt;App /&amp;gt;
  &amp;lt;/React.StrictMode&amp;gt;
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next, App.js should look like this:&lt;br&gt;
this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function App() {
  return (
    &amp;lt;div className="App"&amp;gt;
      &amp;lt;h1&amp;gt;Hello World&amp;lt;/h1&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now let's set up our folder structure and run our application. The folder structure should look like this (create directories and files as needed):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/frontend
    /src
        /components
            /MoodInput
            /MoodList
            /MoodChart
        /services
            /apiService.js
        /assets
            /styles
                /main.css
        App.js
        index.js
    /public
        index.html
    package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Inside your terminal, run the following command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;A new tab will open in your default browser and navigate to &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000/&lt;/a&gt;. You should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvezkgaihi1ygwbuddp27.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvezkgaihi1ygwbuddp27.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great! Let's start with our API service to add our CRUD functionality. We need methods for GET, POST, PUT, and DELETE requests. &lt;/p&gt;

&lt;p&gt;Open apiService.js and insert the following code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const API_URL = "http://localhost:3001";

export const getMoodsAPI = async () =&amp;gt; {
  const response = await fetch(`${API_URL}/moods`);
  const data = await response.json();
  return data;
};

export const addMoodAPI = async (mood) =&amp;gt; {
  const response = await fetch(`${API_URL}/moods`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ mood }),
  });
  const data = await response.json();
  return data;
};

// Update mood
export const updateMoodAPI = async (id, updatedMood) =&amp;gt; {
  const response = await fetch(`${API_URL}/moods/${id}`, {
    method: "PUT",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(updatedMood),
  });

  if (!response.ok) {
    throw new Error("Failed to update mood");
  }

  return response.json();
};

// Delete mood
export const deleteMoodAPI = async (id) =&amp;gt; {
  const response = await fetch(`${API_URL}/moods/${id}`, {
    method: "DELETE",
  });

  if (!response.ok) {
    throw new Error("Failed to delete mood");
  }

  return response.json();
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here's what each function does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;getMoodsAPI: Fetches all moods from the API.&lt;/li&gt;
&lt;li&gt;addMoodAPI: Sends a POST request to add a new mood.&lt;/li&gt;
&lt;li&gt;updateMoodAPI: Sends a PUT request to update a specific mood by ID.&lt;/li&gt;
&lt;li&gt;deleteMoodAPI: Sends a DELETE request to remove a mood by ID.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that our API service is ready, let's build our components. &lt;/p&gt;

&lt;p&gt;Start with MoodInput.js. Open the file and paste this code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from "react";

const MoodInput = ({ addMood }) =&amp;gt; {
  const [mood, setMood] = useState("");
  const [error, setError] = useState(null);

  const handleSubmit = (e) =&amp;gt; {
    e.preventDefault();
    if (mood === "" || mood &amp;gt; 10) {
      setError("Please enter a value between 1 and 10");
    } else {
      setError(null);
      addMood(mood);
      setMood("");
    }
  };

  return (
    &amp;lt;form onSubmit={handleSubmit} className="mood-form"&amp;gt;
      &amp;lt;label htmlFor="mood-input"&amp;gt;
        On a scale of 1-10, how are you feeling today?
      &amp;lt;/label&amp;gt;
      &amp;lt;input
        id="mood-input"
        type="number"
        min="1"
        max="10"
        value={mood}
        onChange={(e) =&amp;gt; setMood(e.target.value)}
      /&amp;gt;
      &amp;lt;button type="submit"&amp;gt;Submit&amp;lt;/button&amp;gt;
      {error &amp;amp;&amp;amp; &amp;lt;p&amp;gt;{error}&amp;lt;/p&amp;gt;}
    &amp;lt;/form&amp;gt;
  );
};

export default MoodInput;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this component:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We use the useState hook to manage the mood and error states.&lt;br&gt;
The handleSubmit function handles form submission. Validates the mood input, and adds the mood if valid.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The form includes an input for the mood and a submit button.&lt;br&gt;
If the input has an error we render an error message.&lt;br&gt;
Finally, we export the MoodInput component.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, let's create the MoodList component. This component will display all moods. Paste the following code inside the MoodList.js file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from "react";
import {
  updateMoodAPI,
  deleteMoodAPI,
} from "../../services/apiService/moodService";

const MoodList = ({ moods, deleteMood, updateMood }) =&amp;gt; {
  const [editingMoodId, setEditingMoodId] = useState(null);
  const [editingMoodValue, setEditingMoodValue] = useState("");

  const handleUpdateMood = async (id) =&amp;gt; {
    try {
      const updated = await updateMoodAPI(id, { mood: editingMoodValue });
      updateMood(id, updated);
      setEditingMoodId(null);
      setEditingMoodValue("");
    } catch (error) {
      console.error(error);
    }
  };

  const handleDeleteMood = async (id) =&amp;gt; {
    try {
      await deleteMoodAPI(id);
      deleteMood(id);
    } catch (error) {
      console.error(error);
    }
  };

  return (
    &amp;lt;div className="mood-list"&amp;gt;
      &amp;lt;ul&amp;gt;
        {moods?.map((mood, index) =&amp;gt; (
          &amp;lt;li key={index}&amp;gt;
            {index}-
            {editingMoodId === mood.id ? (
              &amp;lt;&amp;gt;
                &amp;lt;input
                  type="number"
                  min="1"
                  max="10"
                  value={editingMoodValue}
                  onChange={(e) =&amp;gt; setEditingMoodValue(e.target.value)}
                /&amp;gt;
                &amp;lt;button onClick={() =&amp;gt; handleUpdateMood(mood.id)}&amp;gt;Save&amp;lt;/button&amp;gt;
              &amp;lt;/&amp;gt;
            ) : (
              &amp;lt;&amp;gt;
                {mood.mood}
                &amp;lt;button
                  onClick={() =&amp;gt; {
                    setEditingMoodId(mood.id);
                    setEditingMoodValue(mood.mood);
                  }}
                &amp;gt;
                  Edit
                &amp;lt;/button&amp;gt;
              &amp;lt;/&amp;gt;
            )}
            &amp;lt;button onClick={() =&amp;gt; handleDeleteMood(mood.id)}&amp;gt;Delete&amp;lt;/button&amp;gt;
          &amp;lt;/li&amp;gt;
        ))}
      &amp;lt;/ul&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default MoodList;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this component:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We import the necessary hooks and API services.&lt;/li&gt;
&lt;li&gt;We define the MoodList functional component, initializing the state for the ID and value of the mood being edited.&lt;/li&gt;
&lt;li&gt;The handleUpdateMood and handleDeleteMood methods use the API service methods for updating and deleting moods. We use try-catch blocks for error handling.&lt;/li&gt;
&lt;li&gt;When rendering, we map over the moods and create a list item for each one. If the current mood is being edited, an input and save button are displayed. Otherwise, we display the current mood with an edit button. The delete button is always available.
*Finally, we export the MoodList component.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'll add a chart component for a visual representation of the moods. &lt;/p&gt;

&lt;p&gt;This component uses the open-source libraries react-chartjs-2 and chart.js. Run the following command to install them:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save react-chartjs-2 chart.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After installing the dependencies, paste the following code inside the MoodChart component:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  Title,
  Tooltip,
  Legend,
} from "chart.js";
import { Line } from "react-chartjs-2";

ChartJS.register(
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  Title,
  Tooltip,
  Legend
);

const MoodChart = ({ moods }) =&amp;gt; {
  const moodValues = moods?.map((mood) =&amp;gt; Number(mood.mood));
  const data = {
    labels: moods?.map((mood, index) =&amp;gt; `Day ${index + 1}`),
    datasets: [
      {
        label: "Mood",
        data: moodValues,
        borderColor: "rgb(75, 192, 192)",
        backgroundColor: "rgba(75, 192, 192, 0.5)",
      },
    ],
  };
  const options = {
    responsive: true,
    plugins: {
      legend: {
        position: "top",
      },
      title: {
        display: true,
        text: "Mood Chart",
      },
    },
    scales: {
      x: {
        type: "category",
      },
      y: {
        type: "linear",
        beginAtZero: true,
      },
    },
  };

  return &amp;lt;Line options={options} data={data} /&amp;gt;;
};

export default MoodChart;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this component:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We import the necessary libraries and components.&lt;/li&gt;
&lt;li&gt;Then register the required Chart.js components.&lt;/li&gt;
&lt;li&gt;Inside our MoodChart component. we map through the moods array to extract mood values and labels.&lt;/li&gt;
&lt;li&gt;We define the data and options for the chart.&lt;/li&gt;
&lt;li&gt;The Line chart component is rendered with the required properties.&lt;/li&gt;
&lt;li&gt;Finally, we export the MoodChart component.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we have our components, it's time to import them into App.js. Add the following code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useEffect } from "react";
import MoodChart from "./components/MoodChart/MoodChart";
import MoodInput from "./components/MoodInput/MoodInput";
import MoodList from "./components/MoodList/MoodList";
import { getMoodsAPI, addMoodAPI } from "./services/apiService/moodService";
import "./App.css";

function App() {
  const [moods, setMoods] = useState([]);

  const updateMood = (id, updatedMood) =&amp;gt; {
    setMoods((prevMoods) =&amp;gt;
      prevMoods.map((mood) =&amp;gt; (mood.id === id ? updatedMood : mood))
    );
  };

  const deleteMood = (id) =&amp;gt; {
    setMoods((prevMoods) =&amp;gt; prevMoods.filter((mood) =&amp;gt; mood.id !== id));
  };

  useEffect(() =&amp;gt; {
    const fetchMoods = async () =&amp;gt; {
      const moods = await getMoodsAPI();
      setMoods(moods);
    };

    fetchMoods();
  }, []);

  const addMood = async (mood) =&amp;gt; {
    const newMood = await addMoodAPI(mood);
    setMoods([...moods, newMood]);
  };

  return (
    &amp;lt;div className="app"&amp;gt;
      &amp;lt;div className="mood-header"&amp;gt;
        &amp;lt;h1&amp;gt;Mood Tracker&amp;lt;/h1&amp;gt;
        &amp;lt;MoodInput addMood={addMood} /&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div className="mood-container"&amp;gt;
        &amp;lt;MoodList
          moods={moods}
          deleteMood={deleteMood}
          updateMood={updateMood}
        /&amp;gt;
        &amp;lt;MoodChart moods={moods} /&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We import the necessary libraries and newly created components.&lt;/li&gt;
&lt;li&gt;Inside our App component, we initialize the state for moods. Define methods for handling mood creation, updates, and deletions.&lt;/li&gt;
&lt;li&gt;The useEffect hook fetches all moods from our database when the component renders.&lt;/li&gt;
&lt;li&gt;We render our components and pass them the necessary props.&lt;/li&gt;
&lt;li&gt;Finally, we export the App component.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the app and you should see the full functionality now, make sure your server app is running too, and check your console for any errors.&lt;/p&gt;

&lt;p&gt;Amazing! You’ve reached this point, we’ve successfully created a full-stack application. Now, we need to add some styling. In the next section, we’ll cover minor styling tweaks, but feel free to get creative and add your flair.&lt;/p&gt;

&lt;h5&gt;
  
  
  Styling
&lt;/h5&gt;

&lt;p&gt;Open App.css and paste the following code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;body {
    background: mintcream;
}

.mood-header {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    margin-bottom: 20px;
}

.mood-container {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 0.5fr 0.5fr;
    gap: 10px;
}

.mood-form &amp;gt; * {
    margin-left: 10px;
}

.mood-list {
    grid-column: 2;
}

.mood-list li {
    margin-bottom: 10px;
}

.mood-list li button {
    margin-left: 10px;
}

.mood-chart {
    grid-column: 3 / span 2;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here’s what we’re doing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Body: Setting the background color to mintcream.&lt;/li&gt;
&lt;li&gt;Header: Using Flexbox to center items vertically and horizontally, with some space below.&lt;/li&gt;
&lt;li&gt;Mood Container: Using a grid layout to position MoodList and MoodChart. MoodList takes one column, and MoodChart spans two columns, both centered.&lt;/li&gt;
&lt;li&gt;Mood List: Adding space between list items and buttons.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Import App.css in your App.js file, then reload your application to see the changes.&lt;/p&gt;

&lt;h5&gt;
  
  
  Conclusion
&lt;/h5&gt;

&lt;p&gt;Throughout this journey, we built a full-stack application with a React UI, an Express.js server, and SQLite for data storage. We also added some styling using Flexbox and Grid layouts.&lt;/p&gt;

&lt;h5&gt;
  
  
  Next Steps
&lt;/h5&gt;

&lt;p&gt;Here are some ideas for further improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Testing&lt;/strong&gt;: Add tests using Jest and React Testing Library.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Functionality&lt;/strong&gt;: Enhance features, like adding real dates to moods.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Styling&lt;/strong&gt;: Add more styles, such as icons instead of buttons, custom fonts, and shadows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment&lt;/strong&gt;: Deploy the application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for sticking with it! You’ve learned a thing or two. Please share your feedback and like the article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jm27/mood-tracker" rel="noopener noreferrer"&gt;Code Repo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
