React Intermediate Projects

Marka aad rabto inaad barato Programming waxaa muhiim ah inaad practice badan aad sameyso si aad u noqoto qof ku fiican Programming. Waxaan horey u diyaarinay Blog ku saabsan React Beginner Projects oo aan kusoo xusnay Projects-ka Beginner-ka ahaa ee React js.

React Js Beginner Projects (Blog):- https://hirkaab.com/react-beginner-projects/

React Basic Projects (Youtube Videos):- https://youtube.com/playlist?list=PLUmY9cusB7UsbOXQEJjc18JFoLDcvd5zF&si=S7A-2CnbVQZ4_WKE

Haddaan waxaan blog-kaan si faahfaahsan ugu xusi doonnaa Intermediate React Projects. Linkyada aad u baahantahay oo muhiimka ah.

React Course Full Course For FREE on Youtube:-

React Basics:- https://www.youtube.com/playlist?list=PLUmY9cusB7UvWh_PJ_1WDBrtePl7jg7hi

React Intermediate Projects:- https://youtube.com/playlist?list=PLUmY9cusB7UvT6N5h3qsRnXX9lVriwvYx&si=GH9R-R37wvz5T73r

React js Full Course FREE at https://hirkaab.com

Bloggaan waxaad ku arki doontaa 3 Projects oo Intermediate bProjects ah, Projects-kaas waxaad isticmaalnay React Js – Vite iyo Tailwindcss oo aan ku style-kareyney.

Tailwind CSS:- https://v3.tailwindcss.com/docs/guides/vite

React Js with Vite:- https://vite.dev/guide/

1- Expense Tracker

Projects 1aad waa Expense Tracker oo projects ka kooban 3 Components oo aan wax yaalo baddan aan ku baranay.

Projects Structure(Qaabka Folders-ka waa sidaa).

/src
├── /components
│ ├── Balance.jsx
│ ├── ExpenseForm.jsx
│ ├── ExpenseItem.jsx
│ └── ExpenseList.jsx
├── App.js
└── index.css

Code-ka oo dhamaystiran waxaad kala degeysaa Github-ka.

https://github.com/Eng-Mohamed-Dek/Expense-Tracker

Components Kala duwan ee Projects-ka waa kuwaan.

App.js File.

import React, { useState, useEffect } from 'react';
import ExpenseForm from './components/ExpenseForm';
import ExpenseList from './components/ExpenseList';
import Balance from './components/Balance';

function App() {
  // Initialize state from localStorage if available
  const [expenses, setExpenses] = useState(() => {
    const storedExpenses = localStorage.getItem('expenses');
    return storedExpenses ? JSON.parse(storedExpenses) : [];
  });

  // Update localStorage whenever the expenses state changes
  useEffect(() => {
    localStorage.setItem('expenses', JSON.stringify(expenses));
  }, [expenses]);

  // add expenses 
  const addExpense = (expense) => {
    setExpenses((prevExpenses) => [...prevExpenses, expense]);
  };

  // delete expenses 
  const deleteExpense = (id) => {
    const updatedExpenses = expenses.filter((expense) => expense.id !== id);
    setExpenses(updatedExpenses);
  };

  return (
    <div className="min-h-screen bg-gray-100 p-8">
      <div className="max-w-2xl mx-auto bg-white shadow-lg rounded-lg p-6">
        <h1 className="text-3xl font-semibold text-center text-slate-500">Expense Tracker</h1>
        <Balance expenses={expenses} />
        <ExpenseForm addExpense={addExpense} />
        <ExpenseList expenses={expenses} deleteExpense={deleteExpense} />
      </div>
    </div>
  );
}

export default App;




Index.css File.

Code-kaan waa qeybta Tailwind css.
@tailwind base;
@tailwind components;
@tailwind utilities;

body {
    font-family: poppins, sans-serif;
}


Intaana waa in aan ku style-kareyneyno Projects Qeybo kamidah.
.App {
    text-align: center;
    padding: 20px;
}

form {
    margin: 10px;
}

input {
    margin: 5px;
}

button {
    padding: 5px 10px;
}

ul {
    list-style-type: none;
}

h2 {
    color: green;
}


Balance.js File.

import React from 'react';

function Balance({ expenses }) {
  const totalBalance = expenses.reduce((total, expense) => total + expense.amount, 0);

  // .reduce() = reduce the elements of an array into an single value 

  return (
    <div className="my-6 text-center">
      <h2 className="text-2xl font-semibold text-green-600">Balance: ${totalBalance.toFixed(2)}</h2>
    </div>
  );
}

export default Balance;

ExpenseForm.js File.

import React, { useState } from 'react';
import { v4 as uuidv4 } from 'uuid';

function ExpenseForm({ addExpense }) {
  const [expense, setExpense] = useState({ description: '', amount: 0 });

  const handleChange = (e) => {
    const { name, value } = e.target;
    setExpense({ ...expense, [name]: value });
  };

  console.log(expense)

  const handleSubmit = (e) => {
    e.preventDefault();
    if (expense.description && expense.amount > 0) {
      addExpense({ ...expense, id: uuidv4(), amount: parseFloat(expense.amount) });
      // The parseFloat() function parses a string argument and returns a floating point number.
      setExpense({ description: '', amount: 0 });
    }
  };

  return (
    <form onSubmit={handleSubmit} className="space-y-4">
      <div>
        <input
          type="text"
          name="description"
          value={expense.description}
          onChange={handleChange}
          placeholder="Description"
          className="w-full p-3 border border-gray-300 rounded-md"
        />
      </div>
      <div>
        <input
          type="number"
          name="amount"
          value={expense.amount}
          onChange={handleChange}
          placeholder="Amount"
          className="w-full p-3 border border-gray-300 rounded-md"
        />
      </div>
      <button
        type="submit"
        className="w-full py-2 bg-primary text-white font-semibold rounded-md hover:bg-primary-hover transition duration-200"
      >
        Add Expense
      </button>
    </form>
  );
}

export default ExpenseForm;
ExpenseItem.js File.

import { FaTrashAlt } from 'react-icons/fa';

function ExpenseItem({ expense, deleteExpense }) {
  return (
    <li className="flex justify-between items-center py-1 px-3 mt-5 bg-gray-50 rounded-md shadow-sm">
      <span className="text-lg font-medium text-gray-700">{expense.description}</span>
      <span className="text-lg text-gray-600">${expense.amount.toFixed(2)}
     <button
        onClick={() => deleteExpense(expense.id)}
        className="ml-4 text-red-500 hover:text-red-700"
      > <FaTrashAlt className="h-4 w-4 text-red-500 hover:text-red-700" />
      </button>
      </span>
      
    </li>
  );
}

export default ExpenseItem;
ExpenseList.js File.

import React from 'react';
import ExpenseItem from './ExpenseItem';

function ExpenseList({ expenses, deleteExpense }) {
  return (
    <div className="mt-6">
      <h3 className="text-xl font-medium text-center text-gray-800">Expense List</h3>
      <ul className="space-y-4">
        {expenses.map((expense) => (
          <ExpenseItem
            key={expense.id}
            expense={expense}
            deleteExpense={deleteExpense}
          />
        ))}
      </ul>
    </div>
  );
}

export default ExpenseList;

2- Recipe Finder

Projects 2aad waa Recipe Finder oo inoo sameynaya inoo inoo raadiyo cuntooyinka.

Erayga “recipe” waxa uu micnihiisu yahaytilmaamo ama habraaca loo diyaariyo cunto. Waa liis kuu tilmaamaya sida aad u sameyn lahayd cunto gaar ah, iyadoo la tilmaamayo waxyaabaha loo baahan yahay iyo sida loo diyaarinayo.

Tusaale ahaan, haddii aad rabto inaad kariso bariis, recipe-ga waxaa ka mid ah:

  • Waxyaabaha loo baahan yahay: Bariis, biyo, cusbo, saliid.
  • Tallaabooyinka: Sida loo kariyo bariiska, waqtiga la kariyo, iyo sida loo diyaariyo.

Marka si aan u helno dhamaan Recipes cuntooyinka oo dhan waxaan isticmaalnay API-ka ugu caansan taas oo inoo suura gelinaysa inaan helno recipe walba inagoo marka ku raadinayno xarfo sida Rice inaan qorno ama Egg oo kale taasoo kadib ina siinaysa Recipe dhamaystiran.

Linkiga APi-ka aan isticmaalnay:- https://spoonacular.com/food-api

Projects Structure(Qaabka Folders-ka waa sidaa).

/src
├── App.js
└── index.css

Code-ka oo dhamaystiran waxaad kala degeysaa Github-ka.

https://github.com/Eng-Mohamed-Dek/Recipe-Finder

Components Kala duwan ee Projects-ka waa kuwaan.

App.js File


import React, { useState } from 'react';
import axios from 'axios';

function App() {
  const [query, setQuery] = useState('');
  const [recipes, setRecipes] = useState([]);
  const [loading, setLoading] = useState(false);


  // Replace with your own API key and endpoint (Example: Spoonacular API)
  const apiKey = 'YOUR API KEY';
  const apiEndpoint = 'https://api.spoonacular.com/recipes/complexSearch';

  const handleSearch = async () => {
    if (query === '') return;
    setLoading(true);
    try {
      const response = await axios.get(apiEndpoint, {
        params: {
          query: query,
          apiKey: apiKey,
          number: 10,
        },
      });
      setRecipes(response.data.results);
    } catch (error) {
      console.error('Error fetching recipes', error);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="min-h-screen bg-gray-100 flex items-center justify-center">
      <div className="w-full max-w-3xl p-6 bg-white rounded-lg shadow-lg">
        <h1 className="text-4xl font-bold text-center mb-6 text-primary">Recipe Finder</h1>

        {/* Search Input Section */}
        <div className="flex mb-6">
          <input
            type="text"
            placeholder="Search for recipes..."
            className="flex-1 p-3 text-xl border border-gray-300 rounded-l-md focus:outline-none"
            value={query}
            onChange={(e) => setQuery(e.target.value)}
          />
          <button
            onClick={handleSearch}
            className="p-3 px-10 bg-primary text-white rounded-r-md focus:outline-none"
          >
            Search
          </button>
        </div>

        {/* Loader */}
        {loading && <div className="text-center text-xl text-gray-600">Loading...</div>}

        {/* Recipe List */}
        {recipes.length > 0 && (
          <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
            {recipes.map((recipe) => (
              <div key={recipe.id} className="bg-white rounded-lg shadow-md overflow-hidden">
                <img
                  src={recipe.image}
                  alt={recipe.title}
                  className="w-full h-40 object-cover"
                />
                <div className="p-4">
                  <h3 className="text-xl font-semibold text-gray-800">{recipe.title}</h3>
                  <a
                    href={`https://spoonacular.com/recipes/${recipe.title}-${recipe.id}`}
                    target="_blank"
                    rel="noopener noreferrer"
                    className="text-primary hover:underline"
                  >
                    View Recipe
                  </a>
                </div>
              </div>
            ))}
          </div>
        )}

        {/* No Results */}
        {recipes.length === 0 && !loading && query && (
          <div className="text-center text-xl text-gray-600">No recipes found</div>
        )}
      </div>
    </div>
  );
}

export default App;
Index.css File.

@tailwind base;
@tailwind components;
@tailwind utilities;

body {
    font-family: poppins, sans-serif;
}

3- Movie Search App

Projects 3aad waa Movie Search App oo inoo sameynaya inoo inoo Aflaamta aan u baahan nahay waxa una markaas inoo soo saaraayaa Filmkaas Magaciisa, Taariikhda iyo Poster-ka sawirka. kadib marka aan click kusiino waxa uu si toos ah ugu raadinaayaa Google.

Marka si aan u helno dhamaan Film Walba oo aan Raadino waxaan isticmaalnay API-ka ugu caansan taas oo inoo suura gelinaysa inaan helno film walba innagoo marka ku raadinayno Magaca Filmkaas.

Linkiga APi-ka aan isticmaalnay:- https://www.omdbapi.com/

Projects Structure(Qaabka Folders-ka waa sidaa).

/src
├── App.js
├── MovieSearch.js
└── index.css

Code-ka oo dhamaystiran waxaad kala degeysaa Github-ka.

https://github.com/Eng-Mohamed-Dek/Recipe-Finder

Components Kala duwan ee Projects-ka waa kuwaan..

App.js File.


import React from "react";
import MovieSearch from "./MovieSearch";

function App() {
  return (
    <div>
      <MovieSearch />
    </div>
  );
}

export default App
MovieSearch File.

import React, { useState } from "react";
import axios from "axios";

const MovieSearch = () => {
  const [query, setQuery] = useState("");
  const [movies, setMovies] = useState([]);

  const API_KEY = "Your Api key"; // Replace with your OMDb or TMDb API key

  const searchMovies = async () => {
    if (!query) return;
    const response = await axios.get(
      `https://www.omdbapi.com/?s=${query}&apikey=${API_KEY}`
    );
    setMovies(response.data.Search || []);
  };

  // search Movie in the google 
  const [searchQuery, setSearchQuery] = useState("");

  // Function to handle the click event
  const handleSearch = (title) => {
    const googleSearchUrl = `https://www.google.com/search?q=${encodeURIComponent(searchQuery)}`;
    window.open(googleSearchUrl, "_blank");
    setSearchQuery(title)
  };

  return (
    <div className="text-center p-6">
      <h2 className="text-2xl font-bold mb-4">Movie Search App 🎬</h2>
      <input
        type="text"
        className="px-4 py-2 border rounded-l-lg w-1/2 mb-4"
        placeholder="Search for a movie..."
        value={query}
        onChange={(e) => setQuery(e.target.value)}
      />
      <button
        className="bg-primary text-white px-6 py-2 rounded-r-lg"
        onClick={searchMovies}
      >
        Search
      </button>

      <div className="w-[85%] mx-auto grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6 mt-6">
        {movies.map((movie) => (
          <div key={movie.imdbID} className="border p-4 rounded-lg shadow-lg">
            <h3 className="text-xl font-semibold mb-4">{movie.Title} <span className="font-light">({movie.Year})</span></h3>
            <img
              className="w-full h-64 object-contain cursor-pointer"
              onClick={() => handleSearch(movie.Title)}
              src={movie.Poster}
              alt={movie.Title}
            />
          </div>
        ))}
      </div>
    </div>
  );
};

export default MovieSearch;
Index.css File

@tailwind base;
@tailwind components;
@tailwind utilities;

body {
    font-family: poppins, sans-serif;
}

Sidoo kale waxaad heli doontaan bloggan kale ee aan kusoo xusi doonno 4 Projects oo Advanced ah.

Waxaa rajaynaayaa inaad bloggaan aad wax baddan aad ka faa`iideen. marka wixii suaal ah qeybta comment-ka inoogu reeb.

I am Fullstack Developer and Professional Graphic Designer who is Passionate about Teaching Tech Specially Graphic Design, Video Editing, Web Design and Web Development and I am also the CEO and Founder of Hirkaab Academy.

Write a comment

Your email address will not be published. Required fields are marked *

Halkaan Nagala Soo Xariir
error: Content is protected !!