<?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>DEV Community: Mai G.</title>
    <description>The latest articles on DEV Community by Mai G. (@phungmaiton).</description>
    <link>https://dev.to/phungmaiton</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%2F1081052%2F10161fc9-616d-45dc-be54-0b4e13fe950e.png</url>
      <title>DEV Community: Mai G.</title>
      <link>https://dev.to/phungmaiton</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/phungmaiton"/>
    <language>en</language>
    <item>
      <title>GitHub Best Practices for Seamless Team Collaboration</title>
      <dc:creator>Mai G.</dc:creator>
      <pubDate>Thu, 10 Aug 2023 20:34:36 +0000</pubDate>
      <link>https://dev.to/phungmaiton/github-best-practices-for-seamless-team-collaboration-3h91</link>
      <guid>https://dev.to/phungmaiton/github-best-practices-for-seamless-team-collaboration-3h91</guid>
      <description>&lt;p&gt;Let's get real! As developers, we almost always work in a team, and effective collaboration is the key to building successful projects. GitHub, a widely used version control platform, offers a range of features that empower teams to work together seamlessly. To make the most of GitHub's capabilities, here are some best practices to consider when collaborating on a project:&lt;/p&gt;

&lt;h2&gt;
  
  
  Branching Strategy: Keeping Your Work Organized
&lt;/h2&gt;

&lt;p&gt;The #1 rule is: never code on main/master!&lt;/p&gt;

&lt;p&gt;Having a well-defined branching strategy is the foundation of successful teamwork on GitHub. Consider adopting the Gitflow workflow, which encourages the use of different branches for specific purposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Main/Branch: This is your stable codebase. It should always represent production-ready code.&lt;/li&gt;
&lt;li&gt;Develop/Branch: Here, ongoing development takes place. New features and bug fixes are merged into this branch.&lt;/li&gt;
&lt;li&gt;Feature/Branches: Each new feature or task gets its own branch. This isolates changes, making it easier to review, test, and merge.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Clear and Descriptive Branch Naming
&lt;/h2&gt;

&lt;p&gt;Give your branches meaningful names that reflect the work being done. Clear naming conventions make it easier for team members to understand the purpose of a branch at a glance. For example, instead of "feature-123," use something like "feature/user-authentication."&lt;/p&gt;

&lt;h2&gt;
  
  
  Pull Requests (PRs): Collaborative Code Review
&lt;/h2&gt;

&lt;p&gt;PRs are a fundamental aspect of GitHub's collaboration capabilities. They facilitate code review, discussion, and quality assurance before changes are merged into the main codebase. Here's how to maximize their effectiveness:&lt;/p&gt;

&lt;p&gt;Provide a descriptive title and context in the PR description.&lt;br&gt;
Mention relevant team members using the "@" symbol to notify them of the PR.&lt;br&gt;
Encourage thorough code reviews by setting minimum review requirements.&lt;br&gt;
Use the review tools to comment on specific lines of code, suggesting improvements or asking questions.&lt;br&gt;
After feedback, make the necessary changes directly within the branch or respond to comments before merging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Continuous Integration (CI) and Automated Testing
&lt;/h2&gt;

&lt;p&gt;Leverage GitHub Actions or other CI tools to automate testing and integration processes. Set up workflows that run tests whenever a new PR is opened or changes are pushed to a branch. This ensures that only code passing tests can be merged, maintaining the project's stability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Quality: Consistent Formatting and Documentation
&lt;/h2&gt;

&lt;p&gt;Consistency is crucial for maintainable code. Consider implementing code formatting tools like Prettier or ESLint to maintain a consistent coding style across the project. Additionally, encourage thorough documentation within the codebase. Well-documented code is easier to understand and onboard new team members.&lt;/p&gt;

&lt;h2&gt;
  
  
  Regularly Update Your Branches
&lt;/h2&gt;

&lt;p&gt;Keep your local branches up-to-date with the latest changes from the main and develop branches. Regularly pull changes to avoid conflicts and ensure your work is based on the most current codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resolve Conflicts Collaboratively
&lt;/h2&gt;

&lt;p&gt;Conflicts can arise when merging changes from different branches. Embrace conflicts as an opportunity to improve code quality. Resolve conflicts collaboratively, involving team members who worked on the conflicting changes. GitHub provides helpful tools for navigating and resolving conflicts within PRs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Communication and Etiquette
&lt;/h2&gt;

&lt;p&gt;Maintain open communication with your team members. Use GitHub's built-in communication features like issue comments and PR discussions to ask questions, clarify doubts, and share insights. Remember to be respectful and professional in your interactions.&lt;/p&gt;

&lt;p&gt;In conclusion, GitHub's collaborative features are invaluable for efficient team development. By following these best practices, your team can harness GitHub's capabilities to streamline workflows, ensure code quality, and create successful projects collaboratively.&lt;/p&gt;

&lt;p&gt;Remember, successful teamwork goes beyond tools; it's about cultivating a culture of collaboration, openness, and continuous improvement within your development team.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>React: How to Implement Search Location Within Radius Feature</title>
      <dc:creator>Mai G.</dc:creator>
      <pubDate>Fri, 21 Jul 2023 21:50:11 +0000</pubDate>
      <link>https://dev.to/phungmaiton/react-how-to-implement-search-location-within-radius-feature-3p24</link>
      <guid>https://dev.to/phungmaiton/react-how-to-implement-search-location-within-radius-feature-3p24</guid>
      <description>&lt;p&gt;In phase 4 of my Software Engineering Bootcamp at Flatiron, along with 2 other exceptional classmates, we built a full stack app using React front-end and Flask back-end. One of the features that we got questions about during our presentation was how we implemented the search locations within a radius feature, so I figured I'd write my a blog on the steps I took to accomplish this feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Haversine Formula
&lt;/h2&gt;

&lt;p&gt;In a nutshell,  the &lt;strong&gt;haversine formula&lt;/strong&gt; determines the great-circle distance between two points given their longitudes and latitudes. As scary as it might sound, we don't have to reinvent the wheel. You first would need to create an element to store this function which takes in 4 variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default function calculateDistance(lat1, lon1, lat2, lon2) {
  const R = 6371;
  const phi1 = (lat1 * Math.PI) / 180;
  const phi2 = (lat2 * Math.PI) / 180;
  const deltaPhi = ((lat2 - lat1) * Math.PI) / 180;
  const deltaLambda = ((lon2 - lon1) * Math.PI) / 180;

  const a =
    Math.sin(deltaPhi / 2) * Math.sin(deltaPhi / 2) +
    Math.cos(phi1) *
      Math.cos(phi2) *
      Math.sin(deltaLambda / 2) *
      Math.sin(deltaLambda / 2);
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

  const distance = R * c;
  return distance;
}

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Google Maps Geocoding API
&lt;/h2&gt;

&lt;p&gt;Head to this &lt;a href="https://developers.google.com/maps/documentation/geocoding/intro"&gt;link&lt;/a&gt; and obtain your own API key.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.npmjs.com/package/react-geocode"&gt;React Geocode&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Install &lt;strong&gt;React Geocode&lt;/strong&gt; &lt;code&gt;npm i react-geocode&lt;/code&gt; in order to convert the addresses in your app to longitude and latitude. This process is called &lt;em&gt;reverse geocoding&lt;/em&gt;. Additionally, you will also need to build a form to take in user input, and store that using &lt;strong&gt;useState&lt;/strong&gt;. The component where you implement this feature will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Search from "./Search"; # my search form
import calculateDistance from "path";
import Geocode from "react-geocode";
Geocode.setApiKey("YOUR-API-KEY");
import { useState, useEffect } from "react";

export default function YourFunction({searchTerm, setSearchTerm, array}) {
  const [userLocation, setUserLocation] = useState({ lat: 0, lon: 0 }); #store user's input in lat and lon
  const [distanceRadius, setDistanceRadius] = useState(10);
  const [filteredArray, setFilteredArray] = useState([]);

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

&lt;/div&gt;



&lt;p&gt;From here we will need to use the &lt;strong&gt;useEffect&lt;/strong&gt; hook to implement the logic for filtering and sorting your array based on the user's location and the distance radius specified.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  useEffect(() =&amp;gt; {
    if (!searchTerm) {
      setFilteredArray(array);
      return;
    }
    Geocode.fromAddress(searchTerm).then(
      (response) =&amp;gt; {
        const { lat, lng } = response.results[0].geometry.location;
        setUserLocation({ lat: lat, lon: lng });

        const updatedArray = array.map((item) =&amp;gt; ({
          ...item,
          distance: calculateDistance(
            userLocation.lat,
            userLocation.lon,
            item.latitude,
            item.longitude
          ),
        }));

        const filteredArray = updatedArray.filter((item) =&amp;gt; item.distance &amp;lt;= distanceRadius)
        setFilteredArray(filteredArray);
      },
      (error) =&amp;gt; {
        console.error(error);
      }
    );
  }, [searchTerm, array, distanceRadius]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may notice that this &lt;strong&gt;useEffect&lt;/strong&gt; hook has a few dependencies because we want the useEffect to fire every time there's a change in the &lt;strong&gt;searchTerm&lt;/strong&gt;, the &lt;strong&gt;array&lt;/strong&gt; itself as well as the &lt;strong&gt;distanceRadius&lt;/strong&gt; (which is chosen by the user via the Search form).&lt;/p&gt;

&lt;p&gt;Within the &lt;strong&gt;useEffect&lt;/strong&gt;, there is an asynchronous operation: the &lt;strong&gt;Geocode.fromAddress&lt;/strong&gt; function call. This function is used to convert the user's search term (address) into latitude and longitude coordinates. Since this is an asynchronous operation, it might not have the results immediately. By using &lt;strong&gt;useEffect&lt;/strong&gt;, we ensure that this operation will be executed after the initial render and after every subsequent update, depending on the specified dependencies.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;useEffect&lt;/strong&gt; hook also helps in avoiding infinite loops caused by frequent updates. Without &lt;strong&gt;useEffect&lt;/strong&gt;, if we directly put the filtering and sorting logic in the component body, it could lead to a continuous update loop, as the state changes would trigger re-rendering and re-calculating distances over and over again. &lt;strong&gt;useEffect&lt;/strong&gt; ensures that the filtering and sorting logic is executed at the right times without causing infinite re-renders.&lt;/p&gt;

&lt;p&gt;Now that you've got your &lt;strong&gt;filteredArray&lt;/strong&gt;, you just have to map through it the way you want it to display. &lt;/p&gt;

&lt;p&gt;Well... that was the best case scenario if your array already contains longitude and latitude. In our case, I had to convert addresses in each item to longitude and latitude, store all that along with the original data in a new array and pass that array down to the component above instead of the original array that we fetch. If you're in the same boat, follow the steps below.&lt;/p&gt;

&lt;p&gt;Inside of my App.js component, I added the following above my App function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const fetchItemLocation = async (item) =&amp;gt; {
  const { street_address, city, state, country } = item;
  const itemAddress = `${street_address}, ${city}, ${state}, ${country}`;

  try {
    const response = await Geocode.fromAddress(itemAddress);
    const { lat, lng } = response.results[0].geometry.location;
    return { ...item, latitude: lat, longitude: lng };
  } catch (error) {
    console.error(error);
    return null;
  }
};
const calculateLatLongForArray = async (array) =&amp;gt; {
  const updatedArray = await Promise.all(array.map(fetchItemLocation));
  return updatedArray.filter((item) =&amp;gt; item !== null);
};

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  fetchItemLocation function:
&lt;/h2&gt;

&lt;p&gt;This function takes a single item object as its parameter and aims to fetch its latitude and longitude coordinates based on its address information. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We extract the address details (street_address, city, state, and country) from the item object and form a full address string&lt;/li&gt;
&lt;li&gt;We then reverse geocode the address using &lt;strong&gt;Geocode.fromAddress&lt;/strong&gt;. If the geocoding is successful, it extracts the latitude (lat) and longitude (lng) from the response and returns a new object that includes the item's original data along with the calculated latitude and longitude. Otherwise, if will catch error and return &lt;strong&gt;null&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  calculateLatLongForArray function:
&lt;/h2&gt;

&lt;p&gt;This function takes an array of item objects as its parameter and aims to calculate latitude and longitude coordinates for each item in the array using the &lt;strong&gt;fetchItemLocation&lt;/strong&gt; function. We use &lt;strong&gt;Promise.all&lt;/strong&gt; to handle multiple asynchronous calls concurrently on the &lt;strong&gt;array.map(fetchItemLocation)&lt;/strong&gt; expression, which iterates through each item in the array and fetches its latitude and longitude using &lt;strong&gt;fetchItemLocation&lt;/strong&gt;. This creates an array of promises that will resolve to an array of updated item objects (including latitude and longitude) or null if an error occurred during geocoding.&lt;/p&gt;

&lt;p&gt;When all the promises are resolved (or rejected), &lt;strong&gt;Promise.all&lt;/strong&gt; returns the resulting array of updated item objects.&lt;br&gt;
The function then filters out any null values from the array using &lt;code&gt;.filter((item) =&amp;gt; item !== null)&lt;/code&gt;, removing any items where geocoding failed.&lt;/p&gt;

&lt;p&gt;Finally, the &lt;strong&gt;calculateLatLongForArray&lt;/strong&gt; function returns an array of updated item objects, each containing the original item data along with the latitude and longitude information obtained from geocoding. &lt;/p&gt;

&lt;p&gt;Inside of my App function, I had a state to store &lt;strong&gt;updatedArray&lt;/strong&gt; &lt;code&gt;const [updatedArray, setUpdatedArray] = useState([]);&lt;/code&gt; and a loading state to store the loading status of the original array &lt;code&gt;const [isLoading, setIsLoading] = useState(false);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After I fetch the original array using &lt;strong&gt;useEffect&lt;/strong&gt;, it goes through another &lt;strong&gt;useEffect&lt;/strong&gt; hook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; useEffect(() =&amp;gt; {
    if (!isLoading) {
      calculateLatLongForArray(array).then((updatedArray) =&amp;gt; {
        setUpdatedArray(updatedArray);
      });
    }
  }, [isLoading, array]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make sure the second &lt;strong&gt;useEffect&lt;/strong&gt; only runs after the array has fully loaded on the front-end, the &lt;strong&gt;isLoading&lt;/strong&gt; state is necessary. We also added &lt;strong&gt;isLoading&lt;/strong&gt; and array as the dependencies to make sure this &lt;strong&gt;useEffect&lt;/strong&gt; hook runs again whenever those two change. &lt;/p&gt;

&lt;p&gt;Now your &lt;strong&gt;updatedArray&lt;/strong&gt; is ready for the &lt;strong&gt;calculatingDistance&lt;/strong&gt; function! &lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>react</category>
      <category>geocode</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Schedule Function to Run on Specific Date and Time in Python</title>
      <dc:creator>Mai G.</dc:creator>
      <pubDate>Thu, 29 Jun 2023 16:14:57 +0000</pubDate>
      <link>https://dev.to/phungmaiton/how-to-schedule-function-to-run-on-specific-date-and-time-in-python-3gef</link>
      <guid>https://dev.to/phungmaiton/how-to-schedule-function-to-run-on-specific-date-and-time-in-python-3gef</guid>
      <description>&lt;p&gt;During my bootcamp at Flatiron School, I wanted to create a reminder function for a group project's CLI app that would send email reminder to the user on a specific date and time that the user inputs. However, there was no straightforward answer online on how to achieve this, and it took me a whole day to figure it out while overcomplicating the issue. I even tried &lt;a href="https://docs.celeryq.dev/en/stable/#"&gt;Celery&lt;/a&gt; and &lt;a href="https://www.rabbitmq.com/"&gt;RabbitMQ&lt;/a&gt;, but that didn't take me anywhere. So here I am, sharing with you the simple solution with the hope to save you time and energy in case you want to try doing something similar. Here we go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Pmail
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pypi.org/project/pmail/"&gt;Pmail&lt;/a&gt; is a nifty command-line e-mail sender, written in Python that allows you to send email with simple configuration and commands. To install, you'll need to run the following command: &lt;code&gt;pip install pmail&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then to configure, run this command &lt;code&gt;pmail --configure&lt;/code&gt; and just fill out information for each requirement. If you're using Gmail, you will need to create an App password and use that in lieu of your regular email password. You can find the instructions &lt;a href="https://support.google.com/mail/answer/185833?hl=en"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now that we've got the easiest part out of the way, let's move on to the next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Subprocess
&lt;/h2&gt;

&lt;p&gt;In order to run &lt;strong&gt;pmail&lt;/strong&gt; command from inside of the Python script, I had to import the subprocess module. In Python, the &lt;strong&gt;subprocess&lt;/strong&gt; module provides a way to create new processes, interact with them, and manage input/output streams. It allows you to run external programs or system commands from within your Python script. The subprocess module provides various functions and classes to work with processes. In our case, we used &lt;strong&gt;subprocess.run()&lt;/strong&gt;. This function is used to run a command in a new process and wait for it to complete. It is a high-level function that simplifies the process creation and management. Below is a function from our app using &lt;strong&gt;subprocess.run()&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def send_mail(user_email, subject, body):
    command_args = ["pmail", user_email, subject, body]
    try:
        subprocess.run(command_args, check=True)
        print("Email sent successfully!")
    except subprocess.CalledProcessError as e:
        print(f"Error occurred while sending email: {e}")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's an explanation of the code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The function starts by constructing a list called command_args. This list contains the command-line arguments required to invoke &lt;strong&gt;pmail&lt;/strong&gt;. The list includes the user_email, subject, and body as command-line arguments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The subprocess.run() function is used to execute the &lt;strong&gt;pmail&lt;/strong&gt; command with the specified command-line arguments. The &lt;strong&gt;check=True&lt;/strong&gt; parameter ensures that if the &lt;strong&gt;pmail&lt;/strong&gt; command returns a non-zero exit code (indicating an error), a &lt;strong&gt;CalledProcessError&lt;/strong&gt; exception will be raised.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inside the try block, &lt;strong&gt;subprocess.run()&lt;/strong&gt; is called to execute the &lt;strong&gt;pmail&lt;/strong&gt; command. If the command is executed successfully (i.e., returns a zero exit code), the message "Email sent successfully!" is printed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the &lt;strong&gt;subprocess.run()&lt;/strong&gt; call raises a &lt;strong&gt;CalledProcessError&lt;/strong&gt;, it means that the &lt;strong&gt;pmail&lt;/strong&gt; command returned a non-zero exit code, indicating an error. In that case, the exception is caught in the except block, and an error message is printed.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now that we've have written our send_mail function, it's time to introduce the next important element: &lt;strong&gt;APScheduler&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  APScheduler
&lt;/h2&gt;

&lt;p&gt;When you go to Google and search for a method to schedule task in Python, you will definitely find &lt;strong&gt;Scheduler&lt;/strong&gt; first. However, &lt;strong&gt;Scheduler&lt;/strong&gt; is only great for scheduling periodic task, not for scheduling on a specific date and time. So first, let's install &lt;a href="https://apscheduler.readthedocs.io/en/master/userguide.html"&gt;&lt;strong&gt;APScheduler&lt;/strong&gt;&lt;/a&gt;: &lt;code&gt;pip install apscheduler&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then we import the &lt;strong&gt;BackgroundScheduler&lt;/strong&gt; from &lt;strong&gt;APScheduler&lt;/strong&gt; and &lt;strong&gt;datetime&lt;/strong&gt; and &lt;strong&gt;timedelta&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;from apscheduler.schedulers.background import BackgroundScheduler&lt;br&gt;
from datetime import datetime, timedelta&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The BackgroundScheduler is a scheduler that runs in the background and uses a separate thread to execute scheduled tasks. It is suitable for long-running applications or when you want the scheduler to operate independently of the main program's execution.&lt;/p&gt;

&lt;p&gt;Below is a portion of the &lt;strong&gt;reminder&lt;/strong&gt; function that executes the &lt;strong&gt;send_mail&lt;/strong&gt; function at a specific &lt;strong&gt;remind_datetime&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def reminder(applications):
    view_app(applications)
    app_id = input("Enter the ID of the application for this reminder: ")
    when = int(
        input(
            "In how many days would you like to be reminded? (e.g: 0 for today, 1 for tomorrow, etc.)"
        )
    )
    remind_time = input(
        "Enter the time (24-hour format) you want to receive your notification (HH:MM): "
    )
    user_email = input("Enter the email address to receive notification: ")
    reminder_message = input("Enter the reminder message: ")

    today = datetime.today().date()
    remind_date = today + timedelta(days=when)
    remind_date_str = remind_date.strftime("%Y-%m-%d")
    remind_datetime = datetime.strptime(
        remind_date.strftime("%Y-%m-%d") + " " + remind_time, "%Y-%m-%d %H:%M"
    )
    print(
        f"You will be reminded on \033[1;32m{remind_date_str} at {remind_time}\033[0m about the following job application:"
    )

    for application in applications:
        if application.id == int(app_id):
            subject = f"Reminder about the {application.job_title} Application"
            body = f"Regarding {application.job_title} at {application.company.name}.\nHere's your message: {reminder_message}\nGood luck!"

            scheduler = BackgroundScheduler()
            scheduler.add_job(
                send_mail,
                "date",
                run_date=remind_datetime,
                args=[user_email, subject, body],
            )
            scheduler.start()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's an explanation of the reminder function:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;reminder&lt;/strong&gt; function takes a parameter &lt;strong&gt;applications&lt;/strong&gt;, which represents a list of job applications. The function starts by displaying the list of job applications using the &lt;strong&gt;view_app&lt;/strong&gt; function.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It then prompts the user to enter the &lt;strong&gt;ID&lt;/strong&gt; of the application they want to set a reminder for, the &lt;strong&gt;number of days&lt;/strong&gt; from today they want to be reminded, the &lt;strong&gt;time&lt;/strong&gt; (in 24-hour format) they want to receive the notification, their &lt;strong&gt;email address&lt;/strong&gt;, and the &lt;strong&gt;reminder message&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, the function calculates the &lt;strong&gt;remind date&lt;/strong&gt; by adding the specified number of days to the current date using the &lt;strong&gt;datetime.today().date(&lt;/strong&gt;) and &lt;strong&gt;timedelta&lt;/strong&gt; functions. It also formats the remind date as a string in the format &lt;strong&gt;"%Y-%m-%d"&lt;/strong&gt; using &lt;strong&gt;strftime&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The function combines the remind date string and the remind time entered by the user to create a &lt;strong&gt;remind_datetime&lt;/strong&gt; object using &lt;strong&gt;datetime.strptime&lt;/strong&gt;. This object is required in the APScheduler method. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then, the function prints a message indicating the remind date and time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It then iterates over the list of applications to find the application with the matching ID entered by the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inside the loop, the function creates a &lt;strong&gt;subject&lt;/strong&gt; and &lt;strong&gt;body&lt;/strong&gt; for the reminder email based on the &lt;strong&gt;selected application&lt;/strong&gt; and the &lt;strong&gt;reminder message&lt;/strong&gt; entered by the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It creates an instance of the &lt;strong&gt;BackgroundScheduler&lt;/strong&gt; class. The function adds a job to the scheduler using the &lt;strong&gt;add_job&lt;/strong&gt; method. The job is scheduled to run at the &lt;strong&gt;remind_datetime&lt;/strong&gt; specified. It calls the &lt;strong&gt;send_mail&lt;/strong&gt; function with the provided &lt;strong&gt;email address&lt;/strong&gt;, &lt;strong&gt;subject&lt;/strong&gt;, and &lt;strong&gt;body&lt;/strong&gt; as arguments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, the scheduler is started using the start method.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By following the steps above, you'll be able to create an email reminder feature for your CLI app. If you'd like to check out our OnTrack app, check out this &lt;a href="https://github.com/phungmaiton/ontrack"&gt;Github repo&lt;/a&gt;. Hope you find this helpful!&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>python</category>
      <category>scheduletasks</category>
      <category>apscheduler</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Common Mistakes React Beginners Make and How to Avoid Them</title>
      <dc:creator>Mai G.</dc:creator>
      <pubDate>Wed, 07 Jun 2023 18:57:53 +0000</pubDate>
      <link>https://dev.to/phungmaiton/common-mistakes-react-beginners-make-and-how-to-avoid-them-1632</link>
      <guid>https://dev.to/phungmaiton/common-mistakes-react-beginners-make-and-how-to-avoid-them-1632</guid>
      <description>&lt;p&gt;React is such a powerful tool once you've mastered its efficient component-based architecture and powerful state management capabilities. However, as a beginner in React, there were a few (silly) mistakes I made that kept me hung up for several hours. In this article, I will discuss three common mistakes and provide tips on how to avoid them with the hope to help other developers save time and energy from frustration. Lettuce begin! &lt;/p&gt;

&lt;h2&gt;
  
  
  Using the Wrong Brackets: {} vs. ()
&lt;/h2&gt;

&lt;p&gt;One of the most frequent mistakes beginners make in React is &lt;em&gt;definitely&lt;/em&gt; mixing up the use of curly brackets '{}' and parentheses '()' when passing props, rendering components, writing functions. Both of these brackets serve different purposes in React. To avoid this mistake, remember the following guidelines:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;When passing props to a component within a component, use curly brackets&lt;br&gt;
&lt;code&gt;&amp;lt;ExampleComponent propName={prop}/&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When passing props to a component.js file, use {} inside of ()&lt;br&gt;
&lt;code&gt;function Example({prop1, prop2, prop3}) {}&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When writing the return for the main function, use () next to return if you have multiple elements within your main &lt;strong&gt;div&lt;/strong&gt; (which is almost always the case)&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function Example () {
   return (
      &amp;lt;div&amp;gt;
          &amp;lt;div&amp;gt;Example Div 1&amp;lt;/div&amp;gt;
          &amp;lt;div&amp;gt;Example Div 2&amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
   )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;When writing an arrow function inside of your component, use {} if it's multiple lines, but remember you'd need to add "return" so that React knows what to return. But if you're rendering a React component inside a JavaScript function then, you'd need to use ()
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function Example () {

   const filteredArray = array.filter((item) =&amp;gt; {
       return what-you-want-to-return });

   return (
       &amp;lt;div&amp;gt;
       ...
       &amp;lt;/div&amp;gt;
   )
}

// Rendering React Component

function ExampleRender () {
   return (
      &amp;lt;div&amp;gt;
      {array.map(item =&amp;gt; (
         &amp;lt;FunctionYouWantToRender 
             key={item.id} 
             prop={item.prop}
         /&amp;gt;
      )}
      &amp;lt;/div&amp;gt;
   )
}


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

&lt;/div&gt;



&lt;p&gt;By adhering to these guidelines, you can ensure that you use the correct brackets in the appropriate contexts, prevent unnecessary errors in your React code, and avoid pulling your hair due to frustration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Passing Props Down Multiple Components
&lt;/h2&gt;

&lt;p&gt;Being able to pass props down multiple layers of nested components in React is a privilege, but also a curse for beginners as we struggle with passing props through these component hierarchies correctly. Failing to pass props down to child components can result in rendering issues and data inconsistencies.&lt;/p&gt;

&lt;p&gt;To avoid this mistake and ensure you're passing props properly, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Identify the parent-child-sibling relationship between components. Remember you can pass data between a parent and a child component, but you can't pass data directly between siblings. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Identify the necessary data or state that needs to be passed down to a child component.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pass the required props from the parent component to the child component through its attributes.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ParentComponent&amp;gt;
    &amp;lt;ChildComponent prop={value}/&amp;gt;
&amp;lt;/ParentComponent&amp;gt;

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Inside of the child component, receive the props using destructuring or by directly accessing them from the &lt;code&gt;**props**&lt;/code&gt; object.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function ChildComponent ({prop}) {
}

function ChildComponent (props) {
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By following this approach, you establish a clear flow of data between components and ensure that the necessary information is available at each level of your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Forgetting to Save All Edited Components Before Testing in the Browser
&lt;/h2&gt;

&lt;p&gt;I cannot remember how my times I was going insane because I couldn't figure out why changes don't reflect in my browser. Going straight from Vanilla JavaScript to React, it took some time for me to get used to saving all affected components before testing in the browser. &lt;/p&gt;

&lt;p&gt;To avoid this mistake, make it a habit to save all modified components before testing your application. This ensures that the latest changes are applied and visible in the browser. You can either do this manually or turn on that autosave feature. Additionally, using a version control system like Git can help you keep track of changes and revert back if needed. &lt;/p&gt;

&lt;p&gt;These are the most common mistakes my peers and I made while when we first got into React. I hope sharing these would help fellow developers enhance their development workflow and save some time and effort in debugging.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Manipulating the DOM with JavaScript 101</title>
      <dc:creator>Mai G.</dc:creator>
      <pubDate>Sun, 14 May 2023 21:44:07 +0000</pubDate>
      <link>https://dev.to/phungmaiton/manipulating-the-dom-with-javascript-101-12ce</link>
      <guid>https://dev.to/phungmaiton/manipulating-the-dom-with-javascript-101-12ce</guid>
      <description>&lt;h2&gt;
  
  
  What is DOM?
&lt;/h2&gt;

&lt;p&gt;DOM stands for Document Object Model, a programming interface that allows web developers to manipulate HTML and XML files. Using scripting languages such as JavaScript, developers can access and modify the structure, style and content of the DOM to generate dynamic and interactive web pages. In this post, we'll go over the basic steps to manipulate the DOM with JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Access DOM Elements
&lt;/h2&gt;

&lt;p&gt;First and foremost, we need to access the element in the DOM that we need to modify. This can be done in a number of ways, but my favorite way is by the method of &lt;strong&gt;&lt;code&gt;.querySelector()&lt;/code&gt;&lt;/strong&gt;. It would be best to assign that element to a variable. The syntax looks like below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Access element based on id&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;const idName = document.querySelector('#idName');&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Access element based on a class&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;const className = document.querySelector('.className');&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Access element based on a tag&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;const h2 = document.querySelector('h2');&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To access all elements sharing the same class or tag, use &lt;strong&gt;&lt;code&gt;.querySelectorAll()&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Access all h2 elements&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;const h2 = document.querySelectorAll('h2');&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Adding and Removing HTML Elements
&lt;/h2&gt;

&lt;p&gt;Adding or removing HTML elements is one of the most common ways to manipulate the DOM with JavaScript. Before adding an element, we first would need to create it. To create a new element, we use the &lt;strong&gt;&lt;code&gt;.createElement()&lt;/code&gt;&lt;/strong&gt; method:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const newDiv = document.createElement('div');&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After that, we would want to use &lt;strong&gt;&lt;code&gt;.append()&lt;/code&gt;&lt;/strong&gt; to add the new &lt;strong&gt;&lt;code&gt;div&lt;/code&gt;&lt;/strong&gt; element to a another element:&lt;/p&gt;

&lt;p&gt;For example, we would like to add it to the end of the &lt;code&gt;body&lt;/code&gt; element, we would first need to grab the body element&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const body = document.querySelector('body');
body.appendChild(div);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To remove an element from the DOM, we can use the &lt;strong&gt;&lt;code&gt;.remove()&lt;/code&gt;&lt;/strong&gt; method.Of course, we need to start by retrieve the element we would like to remove:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const example = document.querySelector('#example');
example.remove();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Modifying HTML Element Attributes
&lt;/h2&gt;

&lt;p&gt;It is also possible to modify HTML element attributes such as &lt;strong&gt;&lt;code&gt;class&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;id&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;src&lt;/code&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;code&gt;href&lt;/code&gt;&lt;/strong&gt; using JavaScript. See examples below:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Retrieve the image we want to update&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const image = document.querySelector('#imageID');
image.src = "new URL";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;- Add a new class to an element&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const element = document.querySelector('#elementID');
element.classList.add('newClass');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;- Remove a class from an element&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;element.classList.remove('className');&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As you can see, DOM manipulation with JavaScript is a powerful tool for creating dynamic and interactive user interfaces. Once you are proficient in manipulating the DOM with JavaScript, you can open up a world of possibilities for web development projects. In this post, we only cover the most basic DOM manipulation methods. If you're interested in learning more, head to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model"&gt;MDN&lt;/a&gt; for more detailed documents.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
